     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.18
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.11 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 03/03/2022 ] ; 2022 modification (previous: 04/02/2016)
    13                                  ;
    14                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    15                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    16                                  ; <Bell Laboratories (17/3/1972)>
    17                                  ; <Preliminary Release of UNIX Implementation Document>
    18                                  ;
    19                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    20                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    21                                  ;
    22                                  ; ****************************************************************************
    23                                  ; 04/02/2016 (v0.2.0.17) - 03/03/2022 (v0.2.0.18)
    24                                  ; Assembler: NASM 2.15
    25                                  ;	nasm unix386.s -l unix386.lst -o unix386 -Z error.txt
    26                                  
    27                                  ; 24/12/2013
    28                                  
    29                                  ; Entering protected mode:
    30                                  ; Derived from 'simple_asm.txt' source code file and 
    31                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    32                                  ; (gregor.brunmar@home.se)
    33                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    34                                  ;
    35                                  
    36                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    37                                  ; by Michael Chourdakis (2009) 
    38                                  ; http://www.codeproject.com/Articles/45788/
    39                                  ; http://www.michaelchourdakis.com
    40                                  ;
    41                                  
    42                                  ; Global Descriptor Table:
    43                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    44                                  ; by Linus Torvalds (1991-1992)
    45                                  ;
    46                                  
    47                                  KLOAD	equ 10000h ; Kernel loading address
    48                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    49                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    50                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    51                                  ; 19/03/2015
    52                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    53                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    54                                  ; 24/03/2015
    55                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    56                                  ; 19/03/2015
    57                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    58                                  		     ; (at the end of the 1st 4MB)
    59                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    60                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    61                                  
    62                                  ; 27/12/2013
    63                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    64                                  
    65                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    66                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    67                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    68                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    69                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    70                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    71                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    72                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    73                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    74                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    75                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    76                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    77                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    78                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    79                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    80                                  ;----------------------------------------
    81                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    82                                  ;-----------------------------------------------------------------------------
    83                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    84                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    85                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    86                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    87                                  
    88                                  ; Memory Allocation Table Address
    89                                  ; 05/11/2014
    90                                  ; 31/10/2014
    91                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    92                                  					; the 1st 1 MB memory space.
    93                                  					; (This address must be aligned
    94                                  					;  on 128 KB boundary, if it will be
    95                                  					;  changed later.)
    96                                  					; ((lower 17 bits of 32 bit M.A.T.
    97                                  					;   address must be ZERO)).
    98                                  					; ((((Reason: 32 bit allocation 
    99                                  					;     instructions, dword steps)))
   100                                  					; (((byte >> 12 --> page >> 5)))  
   101                                  ;04/11/2014	
   102                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   103                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   104                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   105                                  ;
   106                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   107                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   108                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   109                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   110                                  
   111                                  ; 17/02/2015 (unix386.s)
   112                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   113                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   114                                  ;
   115                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   116                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   117                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   118                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   119                                  
   120                                  
   121                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   122                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   123                                  ;
   124                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   125                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   126                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   127                                  		      ; otherwise it is standard FDPT with physical values 	
   128                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   129                                  		      ; (obsolete for IDE/ATA drives)
   130                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   131                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   132                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   133                                  			; Bit 4 : Reserved. Always 0
   134                                  			; Bit 3 : Set to 1 if more than 8 heads
   135                                  			; Bit 2-0 : Reserved. Alsways 0
   136                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   137                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   138                                  
   139                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   140                                  ; (11 bytes long) will be used by diskette handler/bios
   141                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   142                                  
   143                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   144                                  
   145                                  [ORG 0] 
   146                                  	; 12/11/2014
   147                                  	; Save boot drive number (that is default root drive)
   148 00000000 8816[DA65]              	mov	[boot_drv], dl ; physical drv number
   149                                  
   150                                  	; Determine installed memory
   151                                  	; 31/10/2014
   152                                  	;
   153 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   154 00000007 CD15                    	int	15h	   ; for large configurations
   155 00000009 7308                    	jnc	short chk_ms
   156 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   157 0000000D CD15                    	int	15h
   158                                  	;	   
   159                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   160                                  	;out	70h, al ; select CMOS register
   161                                  	;in	al, 71h ; read data (1 byte)
   162                                  	;mov	cl, al
   163                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   164                                  	;out	70h, al ; select CMOS register
   165                                  	;in	al, 71h ; read data (1 byte)
   166                                  	;mov	ch, al
   167                                   	;      
   168 0000000F 89C1                    	mov	cx, ax
   169 00000011 31D2                    	xor	dx, dx
   170                                  chk_ms:
   171 00000013 890E[7268]              	mov	[mem_1m_1k], cx
   172 00000017 8916[7468]              	mov	[mem_16m_64k], dx
   173                                  	; 05/11/2014
   174                                  	;and	dx, dx
   175                                  	;jz	short L2
   176 0000001B 81F90004                        cmp     cx, 1024
   177 0000001F 7351                    	jnb	short L0
   178                                  		 ; insufficient memory_error	
   179                                  		 ; Minimum 2 MB memory is needed... 
   180                                  	; 05/11/2014
   181                                  	; (real mode error printing)
   182 00000021 FB                      	sti
   183 00000022 BE[3600]                	mov	si, msg_out_of_memory
   184 00000025 BB0700                  	mov	bx, 7
   185 00000028 B40E                    	mov	ah, 0Eh	; write tty
   186                                  oom_1:
   187 0000002A AC                      	lodsb
   188 0000002B 08C0                    	or	al, al
   189 0000002D 7404                    	jz	short oom_2
   190 0000002F CD10                    	int	10h
   191 00000031 EBF7                    	jmp	short oom_1
   192                                  oom_2:
   193 00000033 F4                              hlt
   194 00000034 EBFD                    	jmp	short oom_2
   195                                  
   196                                  ; 04/02/2022
   197                                  ; 05/11/2014
   198                                  msg_out_of_memory:
   199 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   200 00000039 496E73756666696369-             db      'Insufficient memory !'
   200 00000042 656E74206D656D6F72-
   200 0000004B 792021             
   201 0000004E 0D0A                    	db	0Dh, 0Ah
   202                                  _int13h_48h_buffer: 
   203                                  	; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc')
   204 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   204 00000059 324D42206D656D6F72-
   204 00000062 79206973206E656564-
   204 0000006B 65642E29           
   205 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   206                                  
   207                                  L0:
   208                                  %include 'diskinit.inc' ; 07/03/2015
   209                              <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC
   210                              <1> ; Last Modification: 02/01/2022
   211                              <1> 
   212                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   213                              <1> 
   214                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   215                              <1> 
   216                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18)
   217                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   218                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   219                              <1> ;L0:
   220                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   221                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   222 00000072 BA7F00              <1> 	mov	dx, 7Fh
   223                              <1> L1:	
   224 00000075 FEC2                <1> 	inc	dl
   225 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   226                              <1> 			; Phoenix EDD v1.1 - EDD v3
   227 00000079 BBAA55              <1> 	mov	bx, 55AAh
   228 0000007C CD13                <1> 	int 	13h
   229 0000007E 721A                <1> 	jc	short L2
   230                              <1> 
   231 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   232 00000084 7514                <1> 	jne	short L2
   233 00000086 FE06[DD65]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   234 0000008A 8816[DC65]          <1>         mov     [last_drv], dl  ; last hard disk number
   235 0000008E BB[6065]            <1> 	mov	bx, hd0_type - 80h
   236 00000091 01D3                <1> 	add	bx, dx	 
   237 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   238                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   239                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   240                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   241                              <1>                          ;            (EDD) ready (DPTE ready)
   242                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   243                              <1>                          ;            (EDD-3)
   244                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   245 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   246 00000098 72DB                <1> 	jb	short L1
   247                              <1> L2:
   248                              <1> 	; 23/11/2014
   249                              <1> 	; 19/11/2014
   250 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   251                              <1> 	; 04/02/2016 (esi -> si)
   252 0000009C BE[DE65]            <1> 	mov	si, fd0_type
   253                              <1> L3:
   254                              <1> 	; 14/01/2015
   255 0000009F 8816[DB65]          <1> 	mov	[drv], dl
   256                              <1> 	;
   257 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   258 000000A5 CD13                <1> 	int	13h	
   259 000000A7 7210                <1> 	jc	short L4
   260                              <1> 		; BL = drive type (for floppy drives)
   261                              <1> 		; DL = number of floppy drives
   262                              <1> 		;		
   263                              <1> 		; ES:DI = Address of DPT from BIOS
   264                              <1> 		;
   265 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   266                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   267                              <1> 	; 14/01/2015
   268 000000AB E8BB01              <1> 	call	set_disk_parms
   269                              <1> 	; 10/12/2014
   270 000000AE 81FE[DE65]          <1> 	cmp	si, fd0_type
   271 000000B2 7705                <1> 	ja	short L4
   272 000000B4 46                  <1> 	inc	si ; fd1_type
   273 000000B5 B201                <1> 	mov	dl, 1
   274 000000B7 EBE6                <1> 	jmp	short L3
   275                              <1> L4:
   276                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   277 000000B9 B27F                <1> 	mov	dl, 7Fh
   278                              <1> 	; 24/12/2014 (Temporary)
   279 000000BB 803E[DD65]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   280                              <1> 	;ja	L10       ; yes, all fixed disk operations
   281                              <1> 			  ; will be performed according to
   282                              <1> 			  ; present EDD specification
   283                              <1> 	; 02/01/2022
   284 000000C0 7603                <1> 	jna	short L5
   285 000000C2 E99100              <1> 	jmp	L10
   286                              <1> L5:
   287 000000C5 FEC2                <1> 	inc 	dl
   288 000000C7 8816[DB65]          <1>         mov     [drv], dl
   289 000000CB 8816[DC65]          <1>         mov     [last_drv], dl ; 14/01/2015
   290 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   291 000000D1 CD13                <1> 	int	13h	; (conventional function)
   292                              <1> 	;jc	L13	; fixed disk drive not ready
   293                              <1> 	; 02/01/2022
   294 000000D3 7303                <1> 	jnc	short L6
   295 000000D5 E98301              <1> 	jmp	L13
   296                              <1> L6:
   297 000000D8 8816[DD65]          <1>         mov     [hdc], dl ; number of drives
   298                              <1> 	;; 14/01/2013
   299                              <1> 	;;push	cx
   300 000000DC E88A01              <1> 	call	set_disk_parms
   301                              <1> 	;;pop	cx
   302                              <1> 	;
   303                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   304 000000DF 8A16[DB65]          <1>         mov     dl, [drv]
   305 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   306 000000E6 80FA80              <1> 	cmp	dl, 80h
   307 000000E9 7603                <1> 	jna	short L7
   308 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   309                              <1> L7:	
   310 000000EE 31C0                <1> 	xor	ax, ax
   311 000000F0 8ED8                <1> 	mov	ds, ax
   312 000000F2 8B37                <1>         mov     si, [bx]
   313 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   314 000000F7 8ED8                <1> 	mov	ds, ax
   315 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   316                              <1> 	;jne	L12 ; invalid FDPT
   317                              <1> 	; 02/01/2022
   318 000000FC 7403                <1> 	je	short L7_8
   319 000000FE E95601              <1> 	jmp	L12
   320                              <1> L7_8:
   321 00000101 BF0000              <1> 	mov	di, HD0_DPT
   322 00000104 80FA80              <1> 	cmp	dl, 80h
   323 00000107 7603                <1> 	jna	short L8
   324 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   325                              <1> L8:
   326                              <1> 	; 30/12/2014
   327 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   328 0000010F 8EC0                <1> 	mov	es, ax
   329                              <1> 	; 24/12/2014
   330 00000111 B90800              <1> 	mov	cx, 8
   331 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   332 00000116 8CC8                <1> 	mov	ax, cs
   333 00000118 8ED8                <1> 	mov	ds, ax
   334                              <1> 	; 02/02/2015
   335 0000011A 8A0E[DB65]          <1>         mov     cl, [drv]
   336 0000011E 88CB                <1> 	mov	bl, cl
   337 00000120 B8F001              <1> 	mov	ax, 1F0h
   338 00000123 80E301              <1> 	and	bl, 1
   339 00000126 7406                <1> 	jz	short L9
   340 00000128 C0E304              <1> 	shl	bl, 4
   341 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   342                              <1> L9:
   343 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   344 0000012F 050602              <1> 	add	ax, 206h
   345 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   346 00000133 88D8                <1> 	mov	al, bl
   347 00000135 04A0                <1> 	add	al, 0A0h
   348 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   349                              <1> 	;
   350 00000138 FE06[DB65]          <1> 	inc	byte [drv]
   351 0000013C BB[6065]            <1> 	mov	bx, hd0_type - 80h
   352 0000013F 01CB                <1> 	add	bx, cx
   353 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   354 00000144 A0[DD65]            <1> 	mov	al, [hdc]
   355 00000147 FEC8                <1> 	dec	al
   356                              <1> 	;jz	L13
   357                              <1> 	; 02/01/2022
   358 00000149 7408                <1> 	jz	short L9_10
   359 0000014B 80FA80              <1> 	cmp	dl, 80h
   360                              <1>         ;jna	L5
   361                              <1> 	;jmp	L13
   362                              <1> 	; 02/01/2022
   363 0000014E 7703                <1> 	ja	short L9_10
   364 00000150 E972FF              <1> 	jmp	L5
   365                              <1> L9_10:
   366 00000153 E90501              <1>         jmp     L13
   367                              <1> L10:
   368 00000156 FEC2                <1> 	inc 	dl
   369                              <1> 	; 25/12/2014
   370 00000158 8816[DB65]          <1> 	mov	[drv], dl
   371 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   372 0000015E CD13                <1> 	int	13h	; (conventional function)
   373                              <1> 	;jc	L13
   374                              <1> 	; 02/01/2022
   375 00000160 72F1                <1> 	jc	short L9_10
   376                              <1> 	; 14/01/2015
   377 00000162 8A16[DB65]          <1> 	mov	dl, [drv]
   378 00000166 52                  <1> 	push	dx
   379 00000167 51                  <1> 	push	cx
   380 00000168 E8FE00              <1> 	call	set_disk_parms
   381 0000016B 59                  <1> 	pop	cx
   382 0000016C 5A                  <1> 	pop	dx
   383                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   384                              <1> 	; 04/02/2016 (esi -> si)
   385                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   386                              <1> 	;		 ; at the '_end' of kernel.
   387                              <1> 	;mov	word [si], 30
   388                              <1> 	; 06/07/2016
   389 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   390                              <1> 	; 09/07/2016
   391 00000170 B81E00              <1> 	mov	ax, 001Eh
   392 00000173 8824                <1> 	mov	[si], ah ; 0
   393 00000175 46                  <1> 	inc	si
   394 00000176 8904                <1> 	mov	word [si], ax
   395                              <1>  	; word [si] = 30
   396                              <1> 	;
   397 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   398 0000017A CD13                <1> 	int	13h
   399                              <1>         ;jc	L13
   400                              <1> 	; 02/01/2022
   401 0000017C 72D5                <1> 	jc	short L9_10
   402                              <1> 	; 04/02/2016 (ebx -> bx)
   403                              <1> 	; 14/01/2015
   404                              <1> 	;sub	bx, bx
   405 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   406 00000180 88D3                <1> 	mov	bl, dl
   407 00000182 80EB80              <1> 	sub	bl, 80h
   408 00000185 81C3[E065]          <1> 	add	bx, hd0_type
   409 00000189 8A07                <1> 	mov 	al, [bx]
   410 0000018B 0C80                <1> 	or	al, 80h
   411 0000018D 8807                <1> 	mov 	[bx], al	
   412 0000018F 81EB[DE65]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   413 00000193 81C3[2A66]          <1> 	add	bx, drv.status
   414 00000197 8807                <1> 	mov	[bx], al
   415                              <1> 	; 04/02/2016 (eax -> ax)
   416 00000199 8B4410              <1> 	mov	ax, [si+16]
   417 0000019C 854412              <1> 	test	ax, [si+18]
   418 0000019F 7413                <1> 	jz	short L10_A0h 
   419                              <1> 			; 'CHS only' disks on EDD system 
   420                              <1> 			;  are reported with ZERO disk size
   421 000001A1 81EB[2A66]          <1> 	sub	bx, drv.status
   422 000001A5 C1E302              <1> 	shl	bx, 2
   423 000001A8 81C3[0E66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   424 000001AC 8907                <1> 	mov	[bx], ax
   425 000001AE 8B4412              <1> 	mov	ax, [si+18]
   426                              <1> 	;mov	[bx], ax
   427                              <1> 	; 02/01/2022 (BugFix)
   428 000001B1 894702              <1> 	mov	[bx+2], ax
   429                              <1> 
   430                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   431                              <1> 	 ; for CHS disks (28/02/2015)
   432                              <1> 	; 30/12/2014
   433 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   434 000001B7 88D0                <1> 	mov	al, dl
   435 000001B9 83E003              <1> 	and 	ax, 3
   436 000001BC C0E005              <1> 	shl	al, 5 ; *32
   437 000001BF 01C7                <1> 	add 	di, ax
   438 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   439 000001C4 8EC0                <1> 	mov	es, ax
   440                              <1> 	;
   441 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   442 000001C8 88CC                <1> 	mov	ah, cl	
   443 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   444 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   445 000001CE AB                  <1> 	stosw		
   446 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   447 000001D1 FEC0                <1> 	inc	al
   448 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   449 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   450 000001D6 AA                  <1> 	stosb
   451 000001D7 8A440C              <1> 	mov	al, [si+12]
   452 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   453 000001DB 31C0                <1>  	xor	ax, ax
   454                              <1> 	;dec	ax	 ; 02/01/2015 
   455 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   456                              <1> 	;xor	al, al	 ; 02/01/2015	
   457 000001DE AA                  <1> 	stosb		 ; reserved
   458 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   459                              <1> 		         ; (do not disable retries, 
   460                              <1> 			 ; more than 8 heads)
   461 000001E1 AA                  <1> 	stosb
   462 000001E2 8B4404              <1> 	mov	ax, [si+4]
   463 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   464                              <1> 	;push	ax	 ; 02/01/2015
   465 000001E6 8A4408              <1> 	mov	al, [si+8]
   466 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   467 000001EA 29C0                <1> 	sub 	ax, ax
   468                              <1> 	;pop	ax	 ; 02/01/2015	
   469 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   470 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   471 000001EF 243F                <1> 	and 	al, 3Fh	
   472 000001F1 AA                  <1> 	stosb
   473                              <1> 	;sub	al, al	 ; checksum
   474                              <1> 	;stosb
   475                              <1> 	;
   476 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   477 000001F5 AD                  <1> 	lodsw
   478 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   479 000001F7 AD                  <1> 	lodsw
   480 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   481                              <1> 	;
   482                              <1> 	; checksum calculation
   483 000001F9 89FE                <1> 	mov	si, di
   484 000001FB 06                  <1> 	push	es
   485 000001FC 1F                  <1> 	pop	ds
   486                              <1> 	;mov	cx, 16
   487 000001FD B90F00              <1> 	mov 	cx, 15
   488 00000200 29CE                <1> 	sub	si, cx
   489 00000202 30E4                <1> 	xor	ah, ah
   490                              <1> 	;del	cl
   491                              <1> L11:		
   492 00000204 AC                  <1> 	lodsb
   493 00000205 00C4                <1> 	add	ah, al
   494 00000207 E2FB                <1> 	loop	L11
   495                              <1> 	;
   496 00000209 88E0                <1> 	mov	al, ah
   497 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   498 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   499                              <1> 	;
   500 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   501 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   502                              <1> 	;
   503                              <1> 	; 23/02/2015
   504 00000210 57                  <1> 	push	di
   505                              <1> 	; ES:DI points to DPTE (FDPTE) location
   506                              <1> 	;mov	cx, 8
   507 00000211 B108                <1> 	mov	cl, 8
   508 00000213 F3A5                <1> 	rep	movsw	
   509                              <1> 	;
   510                              <1> 	; 23/02/2015
   511                              <1> 	; (P)ATA drive and LBA validation
   512                              <1> 	; (invalidating SATA drives and setting
   513                              <1> 	; CHS type I/O for old type fixed disks)
   514 00000215 5B                  <1> 	pop	bx
   515 00000216 8CC8                <1> 	mov	ax, cs
   516 00000218 8ED8                <1> 	mov	ds, ax
   517 0000021A 268B07              <1> 	mov	ax, [es:bx]
   518 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   519 00000220 7418                <1> 	je	short L11a
   520 00000222 3D7001              <1> 	cmp	ax, 170h
   521 00000225 7413                <1> 	je	short L11a
   522                              <1> 	; invalidation 
   523                              <1> 	; (because base port address is not 1F0h or 170h)
   524 00000227 30FF                <1> 	xor	bh, bh
   525 00000229 88D3                <1> 	mov	bl, dl
   526 0000022B 80EB80              <1> 	sub	bl, 80h
   527 0000022E C687[E065]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   528 00000233 808F[2C66]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   529 00000238 EB14                <1> 	jmp	short L11b
   530                              <1> L11a:	
   531                              <1> 	; LBA validation
   532 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   533 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   534 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   535                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   536 00000242 28FF                <1> 	sub	bh, bh
   537 00000244 88D3                <1> 	mov	bl, dl
   538 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   539 00000249 80A7[2C66]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   540                              <1> 				; bit 0 = LBA ready bit
   541                              <1> 	; 'diskio' procedure will check this bit !
   542                              <1> L11b:
   543 0000024E 3A16[DC65]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   544 00000252 7307                <1>         jnb     short L13
   545 00000254 E9FFFE              <1>         jmp     L10
   546                              <1> L12:
   547                              <1> 	; Restore data registers
   548 00000257 8CC8                <1> 	mov	ax, cs
   549 00000259 8ED8                <1> 	mov	ds, ax	
   550                              <1> L13:
   551                              <1> 	; 13/12/2014
   552 0000025B 0E                  <1> 	push	cs
   553 0000025C 07                  <1> 	pop	es
   554                              <1> L14:
   555 0000025D B411                <1> 	mov 	ah, 11h
   556 0000025F CD16                <1> 	int 	16h
   557                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   558                              <1> 	; 02/01/2022
   559 00000261 7466                <1> 	jz	short L16
   560 00000263 B010                <1> 	mov	al, 10h
   561 00000265 CD16                <1> 	int 	16h
   562 00000267 EBF4                <1> 	jmp 	short L14
   563                              <1> L15:
   564                              <1> 
   565                              <1> ; //////
   566                              <1> 
   567                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   568                              <1> %if 0
   569                              <1> 	; 24/11/2014
   570                              <1> 	; 19/11/2014
   571                              <1> 	; 14/11/2014
   572                              <1> 	; Temporary code for disk searching code check
   573                              <1> 	;
   574                              <1> 	; This code will show existing (usable) drives and also
   575                              <1> 	; will show EDD interface support status for hard disks		
   576                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   577                              <1> 	; no need to get it again in protected mode...) 
   578                              <1> 	;	
   579                              <1> 	; 13/11/2014
   580                              <1> 	mov	bx, 7
   581                              <1> 	mov	ah, 0Eh
   582                              <1> 	mov	al, [fd0_type]
   583                              <1> 	and	al, al
   584                              <1> 	jz	short L15a
   585                              <1> 	mov	dl, al
   586                              <1> 	mov	al, 'F'
   587                              <1> 	int 	10h
   588                              <1> 	mov	al, 'D'
   589                              <1> 	int 	10h
   590                              <1> 	mov	al, '0'
   591                              <1> 	int 	10h
   592                              <1> 	mov	al, ' '
   593                              <1> 	int	10h
   594                              <1> 	call	L15c
   595                              <1> 	mov	al, ' '
   596                              <1> 	int	10h
   597                              <1> 	;
   598                              <1> 	mov	al, [fd1_type]
   599                              <1> 	and	al, al
   600                              <1> 	jz	short L15a
   601                              <1> 	mov	dl, al
   602                              <1> 	mov	al, 'F'
   603                              <1> 	int 	10h
   604                              <1> 	mov	al, 'D'
   605                              <1> 	int 	10h
   606                              <1> 	mov	al, '1'
   607                              <1> 	int 	10h
   608                              <1> 	mov	al, ' '
   609                              <1> 	int	10h
   610                              <1> 	call	L15c
   611                              <1> 	mov	al, ' '
   612                              <1> 	int	10h
   613                              <1> 	mov	al, ' '
   614                              <1> 	int	10h
   615                              <1> L15a:
   616                              <1> 	mov	al, [hd0_type]
   617                              <1> 	and	al, al
   618                              <1> 	jz	short L15b
   619                              <1> 	mov	dl, al
   620                              <1> 	mov	al, 'H'
   621                              <1> 	int 	10h
   622                              <1> 	mov	al, 'D'
   623                              <1> 	int 	10h
   624                              <1> 	mov	al, '0'
   625                              <1> 	int 	10h
   626                              <1> 	mov	al, ' '
   627                              <1> 	int 	10h
   628                              <1> 	call	L15c
   629                              <1> 	mov	al, ' '
   630                              <1> 	int	10h
   631                              <1> 	;
   632                              <1> 	mov	al, [hd1_type]
   633                              <1> 	and	al, al
   634                              <1> 	jz	short L15b
   635                              <1> 	mov	dl, al
   636                              <1> 	mov	al, 'H'
   637                              <1> 	int 	10h
   638                              <1> 	mov	al, 'D'
   639                              <1> 	int 	10h
   640                              <1> 	mov	al, '1'
   641                              <1> 	int 	10h
   642                              <1> 	mov	al, ' '
   643                              <1> 	int 	10h
   644                              <1> 	call	L15c
   645                              <1> 	mov	al, ' '
   646                              <1> 	int	10h
   647                              <1> 	;
   648                              <1> 	mov	al, [hd2_type]
   649                              <1> 	and	al, al
   650                              <1> 	jz	short L15b
   651                              <1> 	mov	dl, al
   652                              <1> 	mov	al, 'H'
   653                              <1> 	int 	10h
   654                              <1> 	mov	al, 'D'
   655                              <1> 	int 	10h
   656                              <1> 	mov	al, '2'
   657                              <1> 	int 	10h
   658                              <1> 	mov	al, ' '
   659                              <1> 	int 	10h
   660                              <1> 	call	L15c
   661                              <1> 	mov	al, ' '
   662                              <1> 	int	10h
   663                              <1> 	;
   664                              <1> 	mov	al, [hd3_type]
   665                              <1> 	and	al, al
   666                              <1> 	jz	short L15b
   667                              <1> 	mov	dl, al
   668                              <1> 	mov	al, 'H'
   669                              <1> 	int 	10h
   670                              <1> 	mov	al, 'D'
   671                              <1> 	int 	10h
   672                              <1> 	mov	al, '3'
   673                              <1> 	int 	10h
   674                              <1> 	mov	al, ' '
   675                              <1> 	int 	10h
   676                              <1> 	call	L15c
   677                              <1> 	mov	al, ' '
   678                              <1> 	int	10h
   679                              <1> 	;
   680                              <1> L15b:
   681                              <1> 	mov	al, 0Dh
   682                              <1> 	int 	10h	
   683                              <1> 	mov	al, 0Ah
   684                              <1> 	int 	10h
   685                              <1> 	;;xor	ah, ah
   686                              <1> 	;;int 	16h	
   687                              <1> 	;
   688                              <1>         ;jmp	L16  ; jmp short L16
   689                              <1>         ; 02/01/2022
   690                              <1> 	jmp	short L16
   691                              <1> 	;
   692                              <1> L15c:
   693                              <1> 	mov	dh, dl
   694                              <1> 	shr	dh, 4
   695                              <1> 	add	dh, 30h
   696                              <1> 	and	dl, 15
   697                              <1> 	add	dl, 30h
   698                              <1> 	mov	al, dh
   699                              <1> 	int	10h
   700                              <1> 	mov	al, dl
   701                              <1> 	int	10h
   702                              <1> 	retn
   703                              <1> 	;
   704                              <1> 	; end of temporary code for disk searching code check
   705                              <1> 
   706                              <1> %endif
   707                              <1> 
   708                              <1> ; //////
   709                              <1> 
   710                              <1> set_disk_parms:
   711                              <1> 	; 04/02/2016 (ebx -> bx)
   712                              <1> 	; 10/07/2015
   713                              <1> 	; 14/01/2015
   714                              <1> 	;push	bx
   715 00000269 28FF                <1> 	sub	bh, bh
   716 0000026B 8A1E[DB65]          <1> 	mov	bl, [drv]
   717 0000026F 80FB80              <1> 	cmp	bl, 80h
   718 00000272 7203                <1> 	jb	short sdp0
   719 00000274 80EB7E              <1> 	sub	bl, 7Eh
   720                              <1> sdp0:	
   721 00000277 81C3[2A66]          <1> 	add	bx, drv.status
   722 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   723                              <1> 	;
   724 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   725 00000280 88CC                <1> 	mov	ah, cl ; 
   726 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   727 00000285 81EB[2A66]          <1> 	sub	bx, drv.status
   728 00000289 D0E3                <1> 	shl	bl, 1
   729 0000028B 81C3[E465]          <1> 	add	bx, drv.cylinders
   730 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   731 00000290 8907                <1> 	mov	[bx], ax
   732 00000292 50                  <1> 	push	ax ; ** cylinders
   733 00000293 81EB[E465]          <1> 	sub	bx, drv.cylinders
   734 00000297 81C3[F265]          <1> 	add	bx, drv.heads
   735 0000029B 30E4                <1> 	xor	ah, ah
   736 0000029D 88F0                <1> 	mov	al, dh ; heads
   737 0000029F 40                  <1> 	inc	ax
   738 000002A0 8907                <1> 	mov	[bx], ax
   739 000002A2 81EB[F265]          <1>         sub     bx, drv.heads
   740 000002A6 81C3[0066]          <1>         add     bx, drv.spt
   741 000002AA 30ED                <1> 	xor	ch, ch
   742 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   743 000002AF 890F                <1> 	mov	[bx], cx
   744 000002B1 81EB[0066]          <1>         sub     bx, drv.spt
   745 000002B5 D1E3                <1> 	shl	bx, 1
   746 000002B7 81C3[0E66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   747                              <1> 	; LBA size = cylinders * heads * secpertrack
   748 000002BB F7E1                <1> 	mul	cx 
   749 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   750 000002BF 58                  <1> 	pop	ax ; ** cylinders
   751 000002C0 48                  <1> 	dec	ax ; 1 cylinder reserved (!?)
   752 000002C1 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   753 000002C3 8907                <1> 	mov	[bx], ax
   754 000002C5 895702              <1> 	mov	[bx+2], dx
   755                              <1> 	;
   756                              <1> 	;pop	bx
   757 000002C8 C3                  <1> 	retn
   758                              <1> 
   759                              <1> ;align 2
   760                              <1> 
   761                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   762                              <1> ;heads	  :  dw 0, 0, 0, 0, 0, 0
   763                              <1> ;spt	  :  dw 0, 0, 0, 0, 0, 0
   764                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   765                              <1> 
   766                              <1> ;last_drv:
   767                              <1> ;	db  0
   768                              <1> ;drv_status:
   769                              <1> ;	db  0,0,0,0,0,0
   770                              <1> ;	db 0
   771                              <1> 
   772                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   773                              <1> 
   774                              <1> L16:
   209                                  
   210                                  	; 10/11/2014
   211 000002C9 FA                           	cli	; Disable interrupts (clear interrupt flag)
   212                                  		; Reset Interrupt MASK Registers (Master&Slave)
   213                                  	;mov	al, 0FFh	; mask off all interrupts
   214                                  	;out	21h, al		; on master PIC (8259)
   215                                  	;jmp 	$+2  ; (delay)
   216                                  	;out	0A1h, al	; on slave PIC (8259)
   217                                  	;
   218                                  	; Disable NMI 
   219 000002CA B080                    	mov   	al, 80h 
   220 000002CC E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   221                                  	; 23/02/2015
   222 000002CE 90                      	nop			;
   223                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   224                                  				; for preventing unknown state (!?)
   225                                  	;
   226                                   	; 20/08/2014
   227                                  	; Moving the kernel 64 KB back (to physical address 0)
   228                                  	; DS = CS = 1000h
   229                                  	; 05/11/2014
   230 000002CF 31C0                    	xor	ax, ax
   231 000002D1 8EC0                    	mov	es, ax ; ES = 0
   232                                  	;
   233 000002D3 B90040                  	mov	cx, (KEND - KLOAD)/4
   234 000002D6 31F6                    	xor	si, si
   235 000002D8 31FF                    	xor	di, di
   236 000002DA F366A5                  	rep	movsd
   237                                  	;
   238 000002DD 06                      	push	es ; 0
   239 000002DE 68[E202]                	push	L17
   240 000002E1 CB                      	retf
   241                                  	;
   242                                  L17:
   243                                  	; Turn off the floppy drive motor
   244 000002E2 BAF203                          mov     dx, 3F2h
   245 000002E5 EE                              out     dx, al ; 0 ; 31/12/2013
   246                                  
   247                                  	; Enable access to memory above one megabyte
   248                                  L18:
   249 000002E6 E464                    	in	al, 64h
   250 000002E8 A802                    	test	al, 2
   251 000002EA 75FA                            jnz     short L18
   252 000002EC B0D1                    	mov	al, 0D1h	; Write output port
   253 000002EE E664                    	out	64h, al
   254                                  L19:
   255 000002F0 E464                    	in	al, 64h
   256 000002F2 A802                    	test	al, 2
   257 000002F4 75FA                            jnz     short L19
   258 000002F6 B0DF                    	mov	al, 0DFh	; Enable A20 line
   259 000002F8 E660                    	out	60h, al
   260                                  ;L20:
   261                                  	;
   262                                  	; Load global descriptor table register
   263                                  
   264                                          ;mov     ax, cs
   265                                          ;mov     ds, ax
   266                                  
   267 000002FA 2E0F0116[0063]                  lgdt    [cs:gdtd]
   268                                  
   269 00000300 0F20C0                          mov     eax, cr0
   270                                  	; or 	eax, 1
   271 00000303 40                      	inc     ax
   272 00000304 0F22C0                  	mov     cr0, eax
   273                                  
   274                                  	; Jump to 32 bit code
   275                                  	
   276 00000307 66                      	db 66h 			; Prefix for 32-bit
   277 00000308 EA                      	db 0EAh 		; Opcode for far jump
   278 00000309 [0F030000]              	dd StartPM 		; Offset to start, 32-bit
   279                                  				; (1000h:StartPM = StartPM + 10000h)
   280 0000030D 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   281                                  				; assuming that StartPM resides in code32
   282                                  
   283                                  [BITS 32] 
   284                                  
   285                                  StartPM:
   286                                  	; Kernel Base Address = 0 ; 30/12/2013
   287 0000030F 66B81000                	mov ax, KDATA           ; Save data segment identifier
   288 00000313 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   289 00000315 8EC0                           	mov es, ax              ; Move data segment into ES register
   290 00000317 8EE0                           	mov fs, ax              ; Move data segment into FS register
   291 00000319 8EE8                          	mov gs, ax              ; Move data segment into GS register
   292 0000031B 8ED0                            mov ss, ax              ; Move data segment into SS register
   293 0000031D BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   294                                  
   295                                  clear_bss: ; Clear uninitialized data area
   296                                  	; 11/03/2015
   297 00000322 31C0                    	xor	eax, eax ; 0
   298                                  	;mov	ecx, (bss_end - bss_start)/4
   299                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   300                                  	; 27/02/2022
   301 00000324 B9BB050000              	mov	ecx, BSS_SIZE/4
   302 00000329 BF[80680000]            	mov	edi, bss_start
   303 0000032E F3AB                    	rep	stosd  	
   304                                  
   305                                  memory_init:
   306                                  	; Initialize memory allocation table and page tables
   307                                  	; 16/11/2014
   308                                  	; 15/11/2014
   309                                  	; 07/11/2014
   310                                  	; 06/11/2014
   311                                  	; 05/11/2014
   312                                  	; 04/11/2014
   313                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   314                                  	;
   315                                  ;	xor	eax, eax
   316                                  ;	xor 	ecx, ecx
   317 00000330 B108                    	mov	cl, 8
   318 00000332 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   319 00000337 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   320                                  				   ; for the first 1 MB memory
   321                                  	;
   322 00000339 668B0D[72680000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   323                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   324 00000340 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   325 00000344 890D[F06A0000]          	mov	[free_pages], ecx
   326 0000034A 668B15[74680000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   327                                  				   ; between 16 MB and 4 GB.	
   328 00000351 6609D2                  	or	dx, dx
   329 00000354 7413                    	jz	short mi_0
   330                                  	;
   331 00000356 6689D0                  	mov	ax, dx
   332 00000359 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   333 0000035C 0105[F06A0000]          	add	[free_pages], eax
   334 00000362 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   335 00000367 EB07                    	jmp	short mi_1
   336                                  mi_0:
   337 00000369 6689C8                  	mov	ax, cx
   338 0000036C 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   339                                  mi_1:
   340 00000370 A3[EC6A0000]            	mov	[memory_size], eax ; Total available memory in pages
   341                                  				   ; 1 alloc. tbl. bit = 1 memory page
   342                                  				   ; 32 allocation bits = 32 mem. pages   
   343                                  	;
   344 00000375 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   345 0000037A C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   346                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   347                                  				   ;  --> x M.A.T. pages, if y = 0
   348 0000037D 66A3[006B0000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   349 00000383 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   350                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   351 00000386 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   352                                  	; Set/Calculate Kernel's Page Directory Address
   353 00000388 81C300001000            	add	ebx, MEM_ALLOC_TBL
   354 0000038E 891D[E86A0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   355                                  				   ; just after the last M.A.T. page
   356                                  	;
   357 00000394 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   358 00000397 A3[F86A0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   359                                  	;			   ; (allocation status search must be 
   360                                  				   ; stopped after here)	
   361 0000039C 31C0                    	xor	eax, eax
   362 0000039E 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   363 0000039F 6651                    	push	cx
   364 000003A1 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   365                                  				   ; count of 32 allocation bits
   366 000003A4 F3AB                    	rep	stosd
   367 000003A6 6659                    	pop	cx
   368 000003A8 40                      	inc	eax		   ; 0	
   369 000003A9 80E11F                  	and	cl, 31		   ; remain bits
   370 000003AC 7412                    	jz	short mi_4
   371 000003AE 8907                    	mov	[edi], eax	   ; reset	
   372                                  mi_2:
   373 000003B0 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   374 000003B3 FEC9                    	dec	cl
   375 000003B5 7404                    	jz	short mi_3
   376 000003B7 FEC0                    	inc	al
   377 000003B9 EBF5                    	jmp	short mi_2
   378                                  mi_3:
   379 000003BB 28C0                    	sub	al, al	   	   ; 0
   380 000003BD 83C704                  	add	edi, 4		   ; 15/11/2014
   381                                  mi_4:
   382 000003C0 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   383 000003C3 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   384                                  	;	
   385 000003C5 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   386                                  	;	
   387 000003CA 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   388 000003CC 7406                    	jz	short mi_5	  ; jump if EDI points to 
   389                                  				  ;         end of first 16 MB	
   390 000003CE D1E9                    	shr	ecx, 1		  ; convert to dword count
   391 000003D0 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   392 000003D2 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   393                                  				  ; (memory hole under 16 MB)
   394                                  mi_5:
   395 000003D4 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   396 000003D7 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   397 000003D9 9C                      	pushf			  ; 16/11/2014		
   398 000003DA 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   399 000003DB F3AB                    	rep	stosd
   400 000003DD 40                      	inc	eax		  ; 0
   401 000003DE 9D                      	popf			  ; 16/11/2014
   402 000003DF 7305                    	jnc	short mi_6
   403 000003E1 6648                    	dec	ax		  ; eax = 0000FFFFh
   404 000003E3 AB                      	stosd
   405 000003E4 6640                    	inc	ax		  ; 0		
   406                                  mi_6:
   407 000003E6 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   408 000003E8 730A                    	jnb	short mi_7	  ; end of memory allocation table
   409                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   410 000003EA 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   411 000003EC 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   412 000003EE D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   413 000003F0 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   414 000003F2 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   415                                  mi_7:
   416                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   417 000003F4 BA00001000              	mov	edx, MEM_ALLOC_TBL
   418                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   419                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   420 000003F9 668B0D[006B0000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   421 00000400 89D7                    	mov	edi, edx
   422 00000402 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   423                                  				  ; byte offset in M.A.T.
   424                                  				  ; (1 M.A.T. byte points to 
   425                                  				  ;	      32768 bytes)
   426                                  				  ; Note: MEM_ALLOC_TBL address 
   427                                  				  ; must be aligned on 128 KB 
   428                                  				  ; boundary!
   429 00000405 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   430                                  	; eax = 0
   431 00000407 290D[F06A0000]          	sub	[free_pages], ecx ; 07/11/2014
   432                                  mi_8:
   433 0000040D 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   434                                  	;dec	bl
   435 00000410 FEC9                    	dec	cl
   436 00000412 7404                    	jz	short mi_9
   437 00000414 FEC0                    	inc	al
   438 00000416 EBF5                    	jmp	short mi_8
   439                                  mi_9:
   440                                  	;
   441                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   442                                  	;		(allocate pages for system page tables)
   443                                  
   444                                  	; edx = MEM_ALLOC_TBL
   445 00000418 8B0D[EC6A0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   446 0000041E 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   447 00000424 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   448                                  				 ; page table count (PDE count)
   449                                  	;
   450 00000427 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   451                                  	;
   452 00000428 41                      	inc	ecx		 ; +1 for kernel page directory	
   453                                  	;
   454 00000429 290D[F06A0000]          	sub	[free_pages], ecx ; 07/11/2014
   455                                  	;
   456 0000042F 8B35[E86A0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   457 00000435 C1EE0C                  	shr	esi, 12		 ; convert to page number
   458                                  mi_10:
   459 00000438 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   460 0000043A 89C3                    	mov	ebx, eax
   461 0000043C C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   462 0000043F 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   463                                  				 ;   to align on dword boundary
   464 00000442 83E01F                  	and	eax, 31		 ; set allocation bit position 
   465                                  				 ;  (bit 0 to bit 31)
   466                                  	;
   467 00000445 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   468                                  	;
   469 00000447 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   470                                  	;
   471 0000044A 46                      	inc	esi		 ; next page table
   472 0000044B E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   473                                  				 ; (ecx = page table count + 1)		
   474                                  	;
   475 0000044D 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   476                                  	;
   477                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   478                                  	;
   479                                  	; Initialize Kernel's Page Directory
   480 0000044E 8B3D[E86A0000]          	mov	edi, [k_page_dir]
   481 00000454 89F8                    	mov	eax, edi
   482 00000456 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   483                                  		     	      ; supervisor + read&write + present
   484 00000458 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   485                                  mi_11:
   486 0000045A 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   487                                  			        ; EAX points to next page table
   488 0000045F AB                      	stosd
   489 00000460 E2F8                    	loop	mi_11
   490 00000462 29C0                    	sub	eax, eax	; Empty PDE
   491 00000464 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   492 00000468 29D1                    	sub	ecx, edx
   493 0000046A 7402                    	jz	short mi_12
   494 0000046C F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   495                                  	;
   496                                  	; Initialization of Kernel's Page Directory is OK, here.
   497                                  mi_12:
   498                                  	; Initialize Kernel's Page Tables
   499                                  	;
   500                                  	; (EDI points to address of page table 0)
   501                                  	; eax = 0
   502 0000046E 8B0D[EC6A0000]          	mov	ecx, [memory_size] ; memory size in pages
   503 00000474 89CA                    	mov	edx, ecx	; (***)
   504 00000476 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   505                                  			     ; supervisor + read&write + present 	
   506                                  mi_13:
   507 00000478 AB                      	stosd
   508 00000479 0500100000              	add	eax, 4096	
   509 0000047E E2F8                    	loop	mi_13	
   510 00000480 6681E2FF03              	and	dx, 1023	; (***)
   511 00000485 740B                    	jz	short mi_14
   512 00000487 66B90004                	mov	cx, 1024	
   513 0000048B 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   514 0000048E 31C0                    	xor	eax, eax
   515 00000490 F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   516                                  				; of the last page table
   517                                  mi_14:
   518                                  	;  Initialization of Kernel's Page Tables is OK, here.
   519                                  	;
   520 00000492 89F8                    	mov	eax, edi	; end of the last page table page
   521                                  			        ; (beginging of user space pages)
   522 00000494 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   523 00000497 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   524                                  				; aligning on dword boundary	
   525                                  	 
   526 00000499 A3[FC6A0000]            	mov	[first_page], eax
   527 0000049E A3[F46A0000]            	mov	[next_page], eax ; The first free page pointer
   528                                  				 ; for user programs
   529                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   530                                  	;
   531                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   532                                  	;
   533                                  	
   534                                  	; Enable paging
   535                                  	;
   536 000004A3 A1[E86A0000]                    mov     eax, [k_page_dir]
   537 000004A8 0F22D8                  	mov	cr3, eax
   538 000004AB 0F20C0                  	mov	eax, cr0
   539 000004AE 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   540 000004B3 0F22C0                  	mov	cr0, eax
   541                                          ;jmp    KCODE:StartPMP
   542                                  
   543 000004B6 EA                      	db 0EAh 		; Opcode for far jump
   544 000004B7 [BD040000]                      dd StartPMP		; 32 bit offset
   545 000004BB 0800                    	dw KCODE		; kernel code segment descriptor
   546                                  
   547                                  
   548                                  StartPMP:
   549                                  	; 06/11//2014
   550                                  	; Clear video page 0
   551                                  	;
   552                                  	; Temporary Code
   553                                  	;
   554 000004BD B9E8030000              	mov	ecx, 80*25/2
   555 000004C2 BF00800B00              	mov	edi, 0B8000h
   556 000004C7 31C0                    	xor	eax, eax	; black background, black fore color
   557 000004C9 F3AB                    	rep	stosd
   558                                  	
   559                                  	; 19/08/2014
   560                                  	; Kernel Base Address = 0
   561                                  	; It is mapped to (physically) 0 in the page table.
   562                                  	; So, here is exactly 'StartPMP' address.
   563                                  	;
   564                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   565                                  	;;mov	esi, msgPM
   566                                  	;; 14/08/2015 (kernel version message will appear
   567                                  	;;	       when protected mode and paging is enabled)
   568 000004CB B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   569 000004CD BE[40660000]            	mov	esi, msgKVER
   570 000004D2 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   571                                  	; 20/08/2014
   572 000004D7 E892010000              	call	printk
   573                                  
   574                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   575                                  	; // Set IRQ offsets
   576                                  	;
   577                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   578                                  	;
   579                                  					;; ICW1
   580 000004DC B011                    	mov	al, 11h			; Initialization sequence
   581 000004DE E620                    	out	20h, al			; 	8259A-1
   582                                  	; jmp 	$+2
   583 000004E0 E6A0                    	out	0A0h, al		; 	8259A-2
   584                                  					;; ICW2
   585 000004E2 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   586 000004E4 E621                    	out	21h, al			;	for 8259A-1
   587                                  	; jmp 	$+2
   588 000004E6 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   589 000004E8 E6A1                    	out	0A1h, al		; 	for 8259A-2
   590                                  					;
   591 000004EA B004                    	mov	al, 04h			;; ICW3
   592 000004EC E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   593                                  	; jmp 	$+2
   594 000004EE B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   595 000004F0 E6A1                    	out	0A1h, al		;
   596                                  					;; ICW4
   597 000004F2 B001                    	mov	al, 01h	 		;
   598 000004F4 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   599                                  	; jmp 	$+2
   600 000004F6 E6A1                    	out	0A1h, al		;	for both chips.
   601                                  
   602                                  	;mov	al, 0FFh	; mask off all interrupts for now
   603                                  	;out	21h, al
   604                                  	;; jmp 	$+2
   605                                  	;out	0A1h, al
   606                                  
   607                                  	; 02/04/2015
   608                                  	; 26/03/2015 System call (INT 30h) modification
   609                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   610                                  	;
   611                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   612                                  	;  setup_idt:
   613                                  	;
   614                                          ;; 16/02/2015
   615                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   616                                  	; 21/08/2014 (timer_int)
   617 000004F8 BE[0C630000]            	mov	esi, ilist
   618 000004FD 8D3D[80680000]          	lea	edi, [idt]
   619                                  	; 26/03/2015
   620 00000503 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   621                                  	; 02/04/2015
   622 00000508 BB00000800              	mov	ebx, 80000h
   623                                  rp_sidt1:
   624 0000050D AD                      	lodsd
   625 0000050E 89C2                    	mov	edx, eax
   626 00000510 66BA008E                	mov	dx, 8E00h
   627 00000514 6689C3                  	mov	bx, ax
   628 00000517 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   629                                         			        ; /* interrupt gate - dpl=0, present */
   630 00000519 AB                      	stosd	; selector & offset bits 0-15 	
   631 0000051A 89D0                    	mov	eax, edx
   632 0000051C AB                      	stosd	; attributes & offset bits 16-23
   633 0000051D E2EE                    	loop	rp_sidt1
   634 0000051F B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   635                                  rp_sidt2:
   636 00000521 AD                      	lodsd
   637 00000522 21C0                    	and	eax, eax
   638 00000524 7413                    	jz	short rp_sidt3
   639 00000526 89C2                    	mov	edx, eax
   640 00000528 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   641 0000052C 6689C3                  	mov	bx, ax
   642 0000052F 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   643 00000531 AB                      	stosd
   644 00000532 89D0                    	mov	eax, edx
   645 00000534 AB                      	stosd
   646 00000535 E2EA                    	loop	rp_sidt2
   647 00000537 EB16                    	jmp	short sidt_OK
   648                                  rp_sidt3:
   649 00000539 B8[91090000]            	mov	eax, ignore_int
   650 0000053E 89C2                    	mov	edx, eax
   651 00000540 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   652 00000544 6689C3                  	mov	bx, ax
   653 00000547 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   654                                  rp_sidt4:
   655 00000549 AB                      	stosd
   656 0000054A 92                      	xchg	eax, edx
   657 0000054B AB                      	stosd
   658 0000054C 92                      	xchg	edx, eax
   659 0000054D E2FA                    	loop	rp_sidt4
   660                                  sidt_OK: 
   661 0000054F 0F011D[06630000]        	lidt 	[idtd]
   662                                  	;
   663                                  	; TSS descriptor setup ; 24/03/2015
   664 00000556 B8[806A0000]            	mov	eax, task_state_segment
   665 0000055B 66A3[FA620000]          	mov	[gdt_tss0], ax
   666 00000561 C1C010                  	rol	eax, 16
   667 00000564 A2[FC620000]            	mov	[gdt_tss1], al
   668 00000569 8825[FF620000]          	mov	[gdt_tss2], ah
   669 0000056F 66C705[E66A0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   669 00000577 00                 
   670                                  		; 
   671                                  		; IO Map Base address (When this address points
   672                                  		; to end of the TSS, CPU does not use IO port 
   673                                  		; permission bit map for RING 3 IO permissions, 
   674                                  		; access to any IO ports in ring 3 will be forbidden.)
   675                                   		;
   676                                  	;mov	[tss.esp0], esp ; TSS offset 4
   677                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   678 00000578 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   679                                  			 ; occurs (or a system call -software INT- is requested)
   680                                  			 ; while cpu running in ring 3 (in user mode).				
   681                                  			 ; (Kernel stack pointer and segment will be loaded
   682                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   683 0000057C 0F00D8                  	ltr	ax  ; Load task register
   684                                  	;
   685                                  esp0_set0:
   686                                  	; 30/07/2015
   687 0000057F 8B0D[EC6A0000]          	mov 	ecx, [memory_size] ; memory size in pages
   688 00000585 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   689 00000588 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   690                                  			  ; (kernel mode virtual address)
   691 0000058E 7605                    	jna	short esp0_set1
   692                                  	;
   693                                  	; If available memory > CORE (end of the 1st 4 MB)
   694                                  	; set stack pointer to CORE
   695                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   696                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   697 00000590 B900004000              	mov	ecx, CORE
   698                                  esp0_set1:
   699 00000595 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   700                                  esp0_set_ok:
   701                                  	; 30/07/2015 (**tss.esp0**) 
   702 00000597 8925[846A0000]          	mov	[tss.esp0], esp
   703 0000059D 66C705[886A0000]10-             mov     word [tss.ss0], KDATA
   703 000005A5 00                 
   704                                  	; 14/08/2015
   705                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   706                                  	;
   707                                  	;cli	; Disable interrupts (for CPU)
   708                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   709                                  	;
   710 000005A6 30C0                    	xor	al, al		; Enable all hardware interrupts!
   711 000005A8 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   712 000005AA EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   713 000005AC E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   714                                  				; (Even if related hardware component
   715                                  				;  does not exist!)
   716                                  	; Enable NMI 
   717 000005AE B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   718 000005B0 E670                    	out  	70h, al
   719                                  	; 23/02/2015
   720 000005B2 90                      	nop
   721 000005B3 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   722                                  				; for preventing unknown state (!?)
   723                                  	;
   724                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   725                                  	;
   726                                  	; 02/09/2014
   727                                  	;xor	bx, bx
   728                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   729                                  	; 27/02/2022	
   730 000005B5 31DB                    	xor	ebx, ebx
   731 000005B7 31D2                    	xor	edx, edx
   732 000005B9 B602                    	mov	dh, 2
   733 000005BB E8290F0000              	call	set_cpos
   734                                  	;
   735                                  	; 06/11/2014
   736                                  	; Temporary Code
   737                                  	;
   738 000005C0 E8A2100000              	call	memory_info
   739                                  	; 14/08/2015
   740                                  	;call getch ; 28/02/2015
   741                                  drv_init:
   742 000005C5 FB                      	sti	; Enable Interrupts 
   743                                  	; 06/02/2015
   744 000005C6 8B15[E0650000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   745 000005CC 668B1D[DE650000]        	mov	bx, [fd0_type] ; fd0, fd1
   746                                  	; 22/02/2015
   747 000005D3 6621DB                  	and	bx, bx
   748 000005D6 751B                    	jnz	short di1
   749                                  	;
   750 000005D8 09D2                    	or 	edx, edx
   751 000005DA 7529                    	jnz	short di2
   752                                  	;
   753                                  setup_error:
   754 000005DC BE[27670000]            	mov 	esi, setup_error_msg
   755                                  psem:	
   756 000005E1 AC                      	lodsb
   757 000005E2 08C0                    	or	al, al
   758                                  	;jz	short haltx ; 22/02/2015
   759 000005E4 7426                    	jz	short di3
   760 000005E6 56                      	push	esi
   761 000005E7 31DB                    	xor	ebx, ebx ; 0
   762                                  			; Video page 0 (bl=0)
   763 000005E9 B407                    	mov	ah, 07h ; Black background, 
   764                                  			; light gray forecolor
   765 000005EB E8EF0D0000              	call	write_tty
   766 000005F0 5E                      	pop	esi
   767 000005F1 EBEE                    	jmp	short psem
   768                                  
   769                                  di1:
   770                                  	; supress 'jmp short T6'
   771                                  	;  (activate fdc motor control code)
   772 000005F3 66C705[EF060000]90-     	mov	word [T5], 9090h ; nop
   772 000005FB 90                 
   773                                  	;
   774                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   775                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   776                                  	;stosw
   777                                  	;mov 	ax, cs
   778                                  	;stosw
   779                                  	;; 16/02/2015
   780                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   781                                  	;
   782 000005FC E87C1F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   783                                  	;
   784 00000601 09D2                    	or	edx, edx
   785 00000603 7407                            jz      short di3
   786                                  di2:
   787 00000605 E8B81F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   788 0000060A 72D0                            jc      short setup_error
   789                                  di3:
   790 0000060C E82A100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   791                                  	;
   792 00000611 E8105C0000              	call	display_disks ; 07/03/2015  (Temporary)
   793                                  ;haltx:
   794                                  	; 14/08/2015
   795                                  	;call	getch ; 22/02/2015
   796 00000616 FB                      	sti	; Enable interrupts (for CPU)
   797                                  	; 14/08/2015
   798                                  	;mov 	ecx, 0FFFFFFFh
   799                                  	; 16/02/2022
   800 00000617 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   801                                  md_info_msg_wait:
   802 0000061C 51                      	push 	ecx
   803 0000061D B001                    	mov	al, 1
   804 0000061F 8A25[166B0000]          	mov 	ah, [ptty] ; active (current) video page
   805 00000625 E85B590000              	call	getc_n
   806 0000062A 59                      	pop	ecx
   807 0000062B 7502                    	jnz	short md_info_msg_ok
   808 0000062D E2ED                    	loop	md_info_msg_wait
   809                                  md_info_msg_ok:
   810                                  	; 30/06/2015
   811 0000062F E8992C0000              	call	sys_init
   812                                  	;
   813                                  	;jmp 	cpu_reset ; 22/02/2015
   814                                  hang:
   815                                  	; 27/02/2022
   816 00000634 29C0                    	sub	eax, eax
   817                                  _hang: 
   818                                  	; 23/02/2015
   819                                  	;sti			; Enable interrupts
   820 00000636 F4                      	hlt
   821                                  	;
   822                                  	;nop
   823                                  	;; 03/12/2014
   824                                  	;; 28/08/2014
   825                                  	;mov	ah, 11h
   826                                  	;call	getc
   827                                  	;jz      _c8
   828                                  	;
   829                                  	; 23/02/2015
   830                                  	; 06/02/2015
   831                                  	; 07/09/2014
   832 00000637 31DB                    	xor	ebx, ebx
   833 00000639 8A1D[166B0000]          	mov	bl, [ptty]	; active_page
   834 0000063F 89DE                    	mov	esi, ebx
   835 00000641 66D1E6                  	shl 	si, 1
   836 00000644 81C6[186B0000]          	add	esi, ttychr
   837 0000064A 668B06                  	mov	ax, [esi]
   838                                  	;and	ax, ax
   839                                  	;;jz	short _c8
   840                                  	;jz	short hang
   841                                  	; 27/02/2022
   842 0000064D 21C0                    	and	eax, eax
   843 0000064F 74E5                    	jz	short _hang
   844 00000651 66C7060000              	mov	word [esi], 0
   845 00000656 80FB03                  	cmp	bl, 3		; Video page 3
   846                                  	;jb	short _c8
   847 00000659 72D9                    	jb	short hang
   848                                  	;	
   849                                  	; 02/09/2014
   850 0000065B B40E                    	mov	ah, 0Eh		; Yellow character 
   851                                  				; on black background
   852                                  	; 27/02/2022 (32 bit reg push-pop)
   853                                  	; 07/09/2014
   854                                  nxtl:
   855                                  	;push	bx
   856 0000065D 53                      	push	ebx
   857                                  	;
   858                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   859                                  				; bh = 0 (video mode)
   860                                  				; Retro UNIX 386 v1 - Video Mode 0
   861                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   862 0000065E 50                      	push	eax
   863 0000065F E87B0D0000              	call 	write_tty
   864 00000664 58                      	pop	eax
   865                                  	;pop	bx
   866 00000665 5B                      	pop	ebx
   867 00000666 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   868                                  	;jne	short _c8
   869 00000668 75CA                    	jne	short hang
   870 0000066A B00A                    	mov	al, 0Ah		; next line
   871 0000066C EBEF                    	jmp	short nxtl
   872                                  	
   873                                  ;_c8:
   874                                  ;	; 25/08/2014
   875                                  ;	cli				; Disable interrupts
   876                                  ;	mov	al, [scounter + 1]
   877                                  ;	and	al, al
   878                                  ;	jnz	hang
   879                                  ;	call	rtc_p
   880                                  ;	jmp     hang
   881                                  
   882                                  
   883                                  	; 27/08/2014
   884                                  	; 20/08/2014
   885                                  printk:
   886                                          ;mov    edi, [scr_row]
   887                                  pkl:
   888 0000066E AC                      	lodsb
   889 0000066F 08C0                    	or 	al, al
   890 00000671 7404                    	jz	short pkr
   891 00000673 66AB                    	stosw
   892 00000675 EBF7                    	jmp	short pkl
   893                                  pkr:
   894 00000677 C3                      	retn
   895                                  
   896                                  ; 25/07/2015
   897                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   898                                  ; 17/02/2015
   899                                  ; 06/02/2015 (unix386.s)
   900                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   901                                  ;
   902                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   903                                  ;
   904                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   905                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   906                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   907                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   908                                  ;									       :
   909                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   910                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   911                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   912                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   913                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   914                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   915                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   916                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   917                                  ;-------------------------------------------------------------------------------
   918                                  ;
   919                                  
   920                                  timer_int:	; IRQ 0
   921                                  ;int_08h:	; Timer
   922                                  	; 14/10/2015
   923                                  	; Here, we are simulating system call entry (for task switch)
   924                                  	; (If multitasking is enabled, 
   925                                  	; 'clock' procedure may jump to 'sysrelease')
   926 00000678 1E                      	push	ds
   927 00000679 06                      	push	es
   928 0000067A 0FA0                    	push	fs
   929 0000067C 0FA8                    	push	gs
   930 0000067E 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   931 0000067F 66B91000                	mov     cx, KDATA
   932 00000683 8ED9                            mov     ds, cx
   933 00000685 8EC1                            mov     es, cx
   934 00000687 8EE1                            mov     fs, cx
   935 00000689 8EE9                            mov     gs, cx
   936                                  	;
   937 0000068B 0F20D9                  	mov	ecx, cr3
   938 0000068E 890D[31070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   939                                  	;
   940 00000694 3B0D[E86A0000]          	cmp 	ecx, [k_page_dir]
   941 0000069A 741F                    	je	short T3
   942                                  	;
   943                                  	; timer interrupt has been occurred while OS is in user mode
   944 0000069C A3[AC6E0000]            	mov 	[u.r0], eax
   945 000006A1 89E1                    	mov	ecx, esp
   946 000006A3 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   947 000006A6 890D[A46E0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   948 000006AC 8925[A86E0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   949                                  	;
   950 000006B2 8B0D[E86A0000]          	mov	ecx, [k_page_dir]
   951 000006B8 0F22D9                  	mov	cr3, ecx
   952                                  T3:
   953 000006BB FB                      	sti				; INTERRUPTS BACK ON
   954 000006BC 66FF05[646B0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   955 000006C3 7507                    	JNZ	short T4		; GO TO TEST_DAY
   956 000006C5 66FF05[666B0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   957                                  T4:					; TEST_DAY
   958 000006CC 66833D[666B0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   959 000006D4 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   960 000006D6 66813D[646B0000]B0-     	CMP	word [TIMER_LOW],0B0H
   960 000006DE 00                 
   961 000006DF 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   962                                  
   963                                  ;-----	TIMER HAS GONE 24 HOURS
   964                                  	;;SUB	AX,AX
   965                                  	;MOV	[TIMER_HIGH],AX
   966                                  	;MOV	[TIMER_LOW],AX
   967 000006E1 29C0                    	sub	eax, eax
   968 000006E3 A3[646B0000]            	mov	[TIMER_LH], eax
   969                                  	;	
   970 000006E8 C605[686B0000]01        	MOV	byte [TIMER_OFL],1
   971                                  
   972                                  ;-----	TEST FOR DISKETTE TIME OUT
   973                                  
   974                                  T5:
   975                                  	; 23/12/2014
   976 000006EF EB1D                    	jmp	short T6		; will be replaced with nop, nop
   977                                  					; (9090h) if a floppy disk
   978                                  					; is detected.
   979                                  	;mov	al,[CS:MOTOR_COUNT]
   980 000006F1 A0[6B6B0000]            	mov	al, [MOTOR_COUNT]
   981 000006F6 FEC8                    	dec	al
   982                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   983 000006F8 A2[6B6B0000]            	mov	[MOTOR_COUNT], al
   984                                  	;mov	[ORG_MOTOR_COUNT], al
   985 000006FD 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   986 000006FF B0F0                    	mov 	al,0F0h
   987                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   988 00000701 2005[6A6B0000]          	and	[MOTOR_STATUS], al
   989                                  	;and	[ORG_MOTOR_STATUS], al
   990 00000707 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   991                                  					; bit 2 = enable controller
   992                                  					;	1 = normal operation
   993                                  					;	0 = reset	
   994                                  					; bit 0, 1 = drive select
   995                                  					; bit 4-7 = motor running bits 
   996 00000709 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
   997 0000070D EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
   998                                  T6:	
   999                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1000                                  					; TIMER TICK INTERRUPT
  1001                                  	;;inc	word [wait_count] ;;27/02/2015
  1002                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1003                                  	;;;;cli
  1004                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1005 0000070E FF15[29070000]          	call	[x_timer] ; 14/05/2015
  1006                                  T7:
  1007                                  	; 14/10/2015
  1008 00000714 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1009 00000716 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1010 00000717 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1011                                  	;
  1012 00000719 A1[31070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1013 0000071E 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1014                                  	;
  1015 00000721 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1016                                  	;
  1017 00000722 0FA9                    	pop	gs
  1018 00000724 0FA1                    	pop	fs
  1019 00000726 07                      	pop	es
  1020 00000727 1F                      	pop	ds
  1021 00000728 CF                      	iretd	; return from interrupt
  1022                                  
  1023                                  
  1024                                  ; ////////////////
  1025                                  
  1026                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1027                                  x_timer:
  1028 00000729 [35070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1029                                  	;dd	clock
  1030                                  
  1031                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1032                                  x_rtci:
  1033 0000072D [6A0A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1034                                  
  1035                                  ; 14/10/2015
  1036 00000731 00000000                cr3reg: dd 0
  1037                                  
  1038                                  	; 06/02/2015
  1039                                  	; 07/09/2014
  1040                                  	; 21/08/2014
  1041                                  u_timer:
  1042                                  	; 27/02/2022
  1043                                  	; 12/02/2022
  1044                                  ;timer_int:	; IRQ 0
  1045                                  	; 06/02/2015
  1046                                  	;push	eax
  1047                                  	;push	edx
  1048                                  	;push	ecx
  1049                                  	;push	ebx
  1050                                  	;push	ds
  1051                                  	;push	es
  1052                                  	;mov	eax, KDATA
  1053                                  	;mov	ds, ax
  1054                                  	;mov	es, ax
  1055 00000735 FF05[2C6B0000]          	inc	dword [tcount]
  1056 0000073B BB[B0660000]            	mov	ebx, tcountstr + 4
  1057                                  	;mov	ax, [tcount]
  1058                                  	; 27/02/2022
  1059 00000740 A1[2C6B0000]            	mov	eax, [tcount]
  1060                                  	;mov	ecx, 10
  1061 00000745 31C9                    	xor	ecx, ecx
  1062 00000747 B10A                    	mov	cl, 10
  1063                                  rp_divtcnt:
  1064 00000749 31D2                    	xor	edx, edx
  1065 0000074B F7F1                    	div	ecx
  1066 0000074D 80C230                  	add	dl, 30h
  1067 00000750 8813                    	mov	[ebx], dl
  1068                                  	;or	ax, ax
  1069                                  	; 27/02/2022
  1070 00000752 09C0                    	or	eax, eax
  1071 00000754 7403                    	jz	short print_lzero
  1072 00000756 4B                      	dec	ebx
  1073 00000757 EBF0                    	jmp	short rp_divtcnt
  1074                                  print_lzero:
  1075 00000759 81FB[AC660000]          	cmp	ebx, tcountstr
  1076 0000075F 7606                    	jna	short print_tcount
  1077 00000761 4B                      	dec	ebx
  1078 00000762 C60330                   	mov	byte [ebx], 30h
  1079 00000765 EBF2                    	jmp	short print_lzero
  1080                                  print_tcount:
  1081 00000767 56                      	push	esi
  1082 00000768 57                      	push	edi
  1083 00000769 BE[88660000]            	mov	esi, timer_msg ; Timer interrupt message
  1084                                  	;; 07/09/2014
  1085                                  	;mov	bx, 1		; Video page 1
  1086                                  	; 12/02/2022
  1087                                  	;mov	bx, 6		; Video page 6
  1088                                  	; 27/02/2022
  1089 0000076E 29DB                    	sub	ebx, ebx
  1090 00000770 B306                    	mov	bl, 6	; Video page 6
  1091                                  ptmsg:
  1092 00000772 AC                      	lodsb
  1093 00000773 08C0                    	or	al, al
  1094 00000775 740D                    	jz	short ptmsg_ok
  1095 00000777 56                      	push	esi
  1096                                  	;push	bx
  1097                                  	; 27/02/2022
  1098 00000778 53                              push	ebx
  1099 00000779 B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1100 0000077B E85F0C0000              	call 	write_tty
  1101                                  	;pop	bx
  1102                                  	; 27/02/2022
  1103 00000780 5B                      	pop	ebx
  1104 00000781 5E                      	pop	esi
  1105 00000782 EBEE                    	jmp	short ptmsg
  1106                                  	;; 27/08/2014
  1107                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1108                                  	;call	printk
  1109                                  	;
  1110                                  ptmsg_ok:
  1111                                  	; 07/09/2014
  1112                                  	;xor	dx, dx		; column 0, row 0
  1113                                  	; 27/02/2022
  1114 00000784 31D2                    	xor	edx, edx
  1115 00000786 E85E0D0000              	call	set_cpos	; set cursor position to 0,0 
  1116                                  	; 23/02/2015
  1117                                  	; 25/08/2014
  1118                                  	;mov	ebx, scounter		; (seconds counter)
  1119                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1120                                  ;	dec	byte [scounter+1]
  1121                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1122                                  ;	jns	short u_timer_retn
  1123                                  	; 26/02/2015
  1124                                  ;	call	rtc_p
  1125                                  ;	mov	ebx, scounter		; (seconds counter)
  1126                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1127                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1128                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1129                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1130                                  ;	mov	byte [ebx], 5
  1131                                  ;	inc	byte [ebx+1] ; 19
  1132                                  ;;timer_eoi:
  1133                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1134                                  ;;	out	20h, al	; 8259 PORT
  1135                                  	;
  1136                                  ;u_timer_retn:  ; 06/02/2015
  1137 0000078B 5F                      	pop	edi
  1138 0000078C 5E                      	pop	esi
  1139                                  	;pop	es
  1140                                  	;pop	ds
  1141                                  	;pop	ebx
  1142                                  	;pop	ecx
  1143                                  	;pop	edx
  1144                                  	;pop	eax
  1145                                  	;iret
  1146 0000078D C3                      	retn	; 06/02/2015
  1147                                  
  1148                                  	; 28/08/2014
  1149                                  irq0:
  1150 0000078E 6A00                            push 	dword 0
  1151 00000790 EB48                    	jmp	short which_irq
  1152                                  irq1:
  1153 00000792 6A01                            push 	dword 1
  1154 00000794 EB44                    	jmp	short which_irq
  1155                                  irq2:
  1156 00000796 6A02                            push 	dword 2
  1157 00000798 EB40                    	jmp	short which_irq
  1158                                  irq3:
  1159                                  	; 20/11/2015
  1160                                  	; 24/10/2015
  1161 0000079A 2EFF15[E9390000]        	call	dword [cs:com2_irq3]
  1162 000007A1 6A03                    	push 	dword 3
  1163 000007A3 EB35                    	jmp	short which_irq
  1164                                  irq4:
  1165                                  	; 20/11/2015
  1166                                  	; 24/10/2015
  1167 000007A5 2EFF15[E5390000]        	call	dword [cs:com1_irq4]
  1168 000007AC 6A04                            push 	dword 4
  1169 000007AE EB2A                    	jmp	short which_irq
  1170                                  irq5:
  1171 000007B0 6A05                            push 	dword 5
  1172 000007B2 EB26                    	jmp	short which_irq
  1173                                  irq6:
  1174 000007B4 6A06                            push 	dword 6
  1175 000007B6 EB22                    	jmp	short which_irq
  1176                                  irq7:
  1177 000007B8 6A07                            push 	dword 7
  1178 000007BA EB1E                    	jmp	short which_irq
  1179                                  irq8:
  1180 000007BC 6A08                            push 	dword 8
  1181 000007BE EB1A                    	jmp	short which_irq
  1182                                  irq9:
  1183 000007C0 6A09                            push 	dword 9
  1184 000007C2 EB16                    	jmp	short which_irq
  1185                                  irq10:
  1186 000007C4 6A0A                            push 	dword 10
  1187 000007C6 EB12                    	jmp	short which_irq
  1188                                  irq11:
  1189 000007C8 6A0B                            push 	dword 11
  1190 000007CA EB0E                    	jmp	short which_irq
  1191                                  irq12:
  1192 000007CC 6A0C                            push 	dword 12
  1193 000007CE EB0A                    	jmp	short which_irq
  1194                                  irq13:
  1195 000007D0 6A0D                            push 	dword 13
  1196 000007D2 EB06                    	jmp	short which_irq
  1197                                  irq14:
  1198 000007D4 6A0E                            push 	dword 14
  1199 000007D6 EB02                    	jmp	short which_irq
  1200                                  irq15:
  1201 000007D8 6A0F                            push 	dword 15
  1202                                  	;jmp	short which_irq
  1203                                  
  1204                                  	; 27/02/2022
  1205                                  	; 19/10/2015
  1206                                  	; 29/08/2014
  1207                                  	; 21/08/2014
  1208                                  which_irq:
  1209 000007DA 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1210 000007DD 53                      	push	ebx
  1211 000007DE 56                      	push	esi
  1212 000007DF 57                      	push	edi
  1213 000007E0 1E                      	push 	ds
  1214 000007E1 06                      	push 	es
  1215                                  	;
  1216 000007E2 88C3                    	mov	bl, al
  1217                                  	;
  1218 000007E4 B810000000              	mov	eax, KDATA
  1219 000007E9 8ED8                    	mov	ds, ax
  1220 000007EB 8EC0                    	mov	es, ax
  1221                                  	; 19/10/2015
  1222 000007ED FC                      	cld
  1223                                          ; 27/08/2014
  1224 000007EE 8105[38660000]A000-             add     dword [scr_row], 0A0h
  1224 000007F6 0000               
  1225                                  	;
  1226 000007F8 B417                    	mov	ah, 17h	; blue (1) background, 
  1227                                  			; light gray (7) forecolor
  1228 000007FA 8B3D[38660000]                  mov     edi, [scr_row]
  1229 00000800 B049                    	mov	al, 'I'
  1230 00000802 66AB                    	stosw
  1231 00000804 B052                    	mov	al, 'R'
  1232 00000806 66AB                    	stosw
  1233 00000808 B051                    	mov	al, 'Q'
  1234 0000080A 66AB                    	stosw
  1235 0000080C B020                    	mov	al, ' '
  1236 0000080E 66AB                    	stosw
  1237 00000810 88D8                    	mov	al, bl
  1238 00000812 3C0A                    	cmp	al, 10
  1239 00000814 7208                    	jb	short iix
  1240 00000816 B031                    	mov	al, '1'
  1241 00000818 66AB                    	stosw
  1242 0000081A 88D8                    	mov	al, bl
  1243 0000081C 2C0A                    	sub	al, 10
  1244                                  iix:
  1245 0000081E 0430                    	add	al, '0'
  1246 00000820 66AB                    	stosw
  1247 00000822 B020                    	mov	al, ' '
  1248 00000824 66AB                    	stosw
  1249 00000826 B021                    	mov	al, '!'
  1250 00000828 66AB                    	stosw
  1251 0000082A B020                    	mov	al, ' '
  1252 0000082C 66AB                    	stosw
  1253                                  	; 23/02/2015
  1254 0000082E 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1255                                  	;jna	iiret
  1256                                  	; 27/02/2022
  1257 00000831 7604                    	jna	short iiz
  1258                                  iiy:
  1259 00000833 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1260 00000835 E6A0                    	out	0A0h, al ; the 2nd 8259
  1261                                  iiz:
  1262 00000837 E983010000              	jmp     iiret
  1263                                  	;
  1264                                  	; 22/08/2014
  1265                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1266                                  	;out	20h, al	; 8259 PORT
  1267                                  	;
  1268                                  	;pop	es
  1269                                  	;pop	ds
  1270                                  	;pop	edi
  1271                                  	;pop	esi
  1272                                  	;pop	ebx
  1273                                  	;pop 	eax
  1274                                  	;iret
  1275                                  
  1276                                  	; 02/04/2015
  1277                                  	; 25/08/2014
  1278                                  exc0:
  1279 0000083C 6A00                            push 	dword 0
  1280 0000083E E990000000                      jmp     cpu_except
  1281                                  exc1:
  1282 00000843 6A01                            push 	dword 1
  1283 00000845 E989000000                      jmp     cpu_except
  1284                                  exc2:
  1285 0000084A 6A02                            push 	dword 2
  1286 0000084C E982000000                      jmp     cpu_except
  1287                                  exc3:
  1288 00000851 6A03                            push 	dword 3
  1289 00000853 EB7E                            jmp     cpu_except
  1290                                  exc4:
  1291 00000855 6A04                            push 	dword 4
  1292 00000857 EB7A                            jmp     cpu_except
  1293                                  exc5:
  1294 00000859 6A05                            push 	dword 5
  1295 0000085B EB76                            jmp     cpu_except
  1296                                  exc6:
  1297 0000085D 6A06                            push 	dword 6
  1298 0000085F EB72                            jmp     cpu_except
  1299                                  exc7:
  1300 00000861 6A07                            push 	dword 7
  1301 00000863 EB6E                            jmp     cpu_except
  1302                                  exc8:
  1303                                  	; [esp] = Error code
  1304 00000865 6A08                            push 	dword 8
  1305 00000867 EB5C                            jmp     cpu_except_en
  1306                                  exc9:
  1307 00000869 6A09                            push 	dword 9
  1308 0000086B EB66                            jmp     cpu_except
  1309                                  exc10:
  1310                                  	; [esp] = Error code
  1311 0000086D 6A0A                            push 	dword 10
  1312 0000086F EB54                            jmp     cpu_except_en
  1313                                  exc11:
  1314                                  	; [esp] = Error code
  1315 00000871 6A0B                            push 	dword 11
  1316 00000873 EB50                            jmp     cpu_except_en
  1317                                  exc12:
  1318                                  	; [esp] = Error code
  1319 00000875 6A0C                            push 	dword 12
  1320 00000877 EB4C                            jmp     cpu_except_en
  1321                                  exc13:
  1322                                  	; [esp] = Error code
  1323 00000879 6A0D                            push 	dword 13
  1324 0000087B EB48                            jmp     cpu_except_en
  1325                                  exc14:
  1326                                  	; [esp] = Error code
  1327 0000087D 6A0E                            push 	dword 14
  1328 0000087F EB44                    	jmp	short cpu_except_en
  1329                                  exc15:
  1330 00000881 6A0F                            push 	dword 15
  1331 00000883 EB4E                            jmp     cpu_except
  1332                                  exc16:
  1333 00000885 6A10                            push 	dword 16
  1334 00000887 EB4A                            jmp     cpu_except
  1335                                  exc17:
  1336                                  	; [esp] = Error code
  1337 00000889 6A11                            push 	dword 17
  1338 0000088B EB38                    	jmp	short cpu_except_en
  1339                                  exc18:
  1340 0000088D 6A12                            push 	dword 18
  1341 0000088F EB42                    	jmp	short cpu_except
  1342                                  exc19:
  1343 00000891 6A13                            push 	dword 19
  1344 00000893 EB3E                    	jmp	short cpu_except
  1345                                  exc20:
  1346 00000895 6A14                            push 	dword 20
  1347 00000897 EB3A                    	jmp	short cpu_except
  1348                                  exc21:
  1349 00000899 6A15                            push 	dword 21
  1350 0000089B EB36                    	jmp	short cpu_except
  1351                                  exc22:
  1352 0000089D 6A16                            push 	dword 22
  1353 0000089F EB32                    	jmp	short cpu_except
  1354                                  exc23:
  1355 000008A1 6A17                            push 	dword 23
  1356 000008A3 EB2E                    	jmp	short cpu_except
  1357                                  exc24:
  1358 000008A5 6A18                            push 	dword 24
  1359 000008A7 EB2A                    	jmp	short cpu_except
  1360                                  exc25:
  1361 000008A9 6A19                            push 	dword 25
  1362 000008AB EB26                    	jmp	short cpu_except
  1363                                  exc26:
  1364 000008AD 6A1A                            push 	dword 26
  1365 000008AF EB22                    	jmp	short cpu_except
  1366                                  exc27:
  1367 000008B1 6A1B                            push 	dword 27
  1368 000008B3 EB1E                    	jmp	short cpu_except
  1369                                  exc28:
  1370 000008B5 6A1C                            push 	dword 28
  1371 000008B7 EB1A                    	jmp	short cpu_except
  1372                                  exc29:
  1373 000008B9 6A1D                            push 	dword 29
  1374 000008BB EB16                    	jmp	short cpu_except
  1375                                  exc30:
  1376 000008BD 6A1E                            push 	dword 30
  1377 000008BF EB04                    	jmp	short cpu_except_en
  1378                                  exc31:
  1379 000008C1 6A1F                            push 	dword 31
  1380 000008C3 EB0E                            jmp     short cpu_except
  1381                                  
  1382                                  	; 27/02/2022
  1383                                  	; 19/10/2015
  1384                                  	; 19/09/2015
  1385                                  	; 01/09/2015
  1386                                  	; 28/08/2015
  1387                                  	; 28/08/2014
  1388                                  cpu_except_en:
  1389 000008C5 87442404                	xchg	eax, [esp+4] ; Error code
  1390 000008C9 36A3[986B0000]          	mov	[ss:error_code], eax
  1391 000008CF 58                      	pop	eax  ; Exception number
  1392 000008D0 870424                  	xchg	eax, [esp]
  1393                                  		; eax = eax before exception
  1394                                  		; [esp] -> exception number
  1395                                  		; [esp+4] -> EIP to return
  1396                                  	; 19/10/2015
  1397                                  	; 19/09/2015
  1398                                  	; 01/09/2015
  1399                                  	; 28/08/2015
  1400                                  	; 29/08/2014
  1401                                  	; 28/08/2014
  1402                                  	; 25/08/2014
  1403                                  	; 21/08/2014
  1404                                  cpu_except:	; CPU Exceptions
  1405 000008D3 FC                      	cld
  1406 000008D4 870424                  	xchg	eax, [esp] 
  1407                                  		; eax = Exception number
  1408                                  		; [esp] = eax (before exception)	
  1409 000008D7 53                      	push	ebx
  1410 000008D8 56                      	push	esi
  1411 000008D9 57                      	push	edi
  1412 000008DA 1E                      	push 	ds
  1413 000008DB 06                      	push 	es
  1414                                  	; 28/08/2015
  1415 000008DC 66BB1000                	mov	bx, KDATA
  1416 000008E0 8EDB                    	mov	ds, bx
  1417 000008E2 8EC3                    	mov	es, bx
  1418 000008E4 0F20DB                  	mov	ebx, cr3
  1419 000008E7 53                      	push	ebx ; (*) page directory
  1420                                  	; 19/10/2015
  1421 000008E8 FC                      	cld
  1422                                  	; 25/03/2015
  1423 000008E9 8B1D[E86A0000]          	mov	ebx, [k_page_dir]
  1424 000008EF 0F22DB                  	mov	cr3, ebx
  1425                                  	; 28/08/2015
  1426 000008F2 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1427 000008F5 7513                    	jne	short cpu_except_nfp
  1428 000008F7 E88B270000              	call	page_fault_handler
  1429 000008FC 21C0                    	and 	eax, eax
  1430                                          ;jz	iiretp ; 01/09/2015
  1431                                  	; 27/02/2022
  1432 000008FE 7505                    	jnz	short cpu_except_pf
  1433 00000900 E9B6000000              	jmp	iiretp
  1434                                  cpu_except_pf:
  1435 00000905 B80E000000              	mov	eax, 0Eh ; 14
  1436                                  cpu_except_nfp:
  1437                                  	; 02/04/2015
  1438 0000090A BB[34060000]            	mov	ebx, hang
  1439 0000090F 875C241C                	xchg	ebx, [esp+28]
  1440                                  		; EIP (points to instruction which faults)
  1441                                  	  	; New EIP (hang)
  1442 00000913 891D[9C6B0000]          	mov	[FaultOffset], ebx
  1443 00000919 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1444 00000921 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1445                                  	;
  1446 00000929 88C4                    	mov	ah, al
  1447 0000092B 240F                    	and	al, 0Fh
  1448 0000092D 3C09                    	cmp	al, 9
  1449 0000092F 7602                    	jna	short h1ok
  1450 00000931 0407                    	add	al, 'A'-':'
  1451                                  h1ok:
  1452 00000933 D0EC                    	shr	ah, 1
  1453 00000935 D0EC                    	shr	ah, 1
  1454 00000937 D0EC                    	shr	ah, 1
  1455 00000939 D0EC                    	shr	ah, 1
  1456 0000093B 80FC09                  	cmp	ah, 9
  1457 0000093E 7603                    	jna	short h2ok
  1458 00000940 80C407                  	add	ah, 'A'-':'
  1459                                  h2ok:	
  1460 00000943 86E0                    	xchg 	ah, al	
  1461 00000945 66053030                	add	ax, '00'
  1462 00000949 66A3[C4660000]          	mov	[excnstr], ax
  1463                                  	;
  1464                                  	; 29/08/2014
  1465 0000094F A1[9C6B0000]            	mov	eax, [FaultOffset]
  1466 00000954 51                      	push	ecx
  1467 00000955 52                      	push	edx
  1468 00000956 89E3                    	mov	ebx, esp
  1469                                  	; 28/08/2015
  1470 00000958 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1471                                  			  ; to hexadecimal string
  1472                                  	;mov	ecx, 10	    ; divisor to convert	
  1473                                  			    ; binary number to decimal string
  1474                                  b2d1:
  1475 0000095D 31D2                    	xor	edx, edx
  1476 0000095F F7F1                    	div	ecx
  1477                                  	;push	dx
  1478                                  	; 27/02/2022
  1479 00000961 52                      	push	edx
  1480 00000962 39C8                    	cmp	eax, ecx
  1481 00000964 73F7                    	jnb	short b2d1
  1482 00000966 BF[CF660000]            	mov	edi, EIPstr ; EIP value
  1483                                  			    ; points to instruction which faults	
  1484                                  	; 28/08/2015
  1485 0000096B 89C2                    	mov	edx, eax
  1486                                  b2d2:
  1487                                  	;add	al, '0'
  1488 0000096D 8A82[23170000]          	mov	al, [edx+hexchrs]
  1489 00000973 AA                      	stosb		    ; write hexadecimal digit to its place	
  1490 00000974 39E3                    	cmp	ebx, esp
  1491 00000976 7605                    	jna	short b2d3
  1492                                  	; 27/02/2022
  1493 00000978 58                      	pop	eax
  1494                                  	;pop	ax
  1495 00000979 88C2                    	mov	dl, al
  1496 0000097B EBF0                    	jmp	short b2d2
  1497                                  b2d3:
  1498 0000097D B068                    	mov 	al, 'h' ; 28/08/2015
  1499 0000097F AA                      	stosb
  1500 00000980 B020                    	mov	al, 20h	    ; space
  1501 00000982 AA                      	stosb
  1502 00000983 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1503 00000985 AA                      	stosb
  1504                                  	;
  1505 00000986 5A                      	pop	edx
  1506 00000987 59                      	pop	ecx
  1507                                  	;
  1508 00000988 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1509                                  			; white (F) forecolor
  1510 0000098A BE[B4660000]            	mov	esi, exc_msg ; message offset
  1511                                  	;
  1512 0000098F EB11                    	jmp	short piemsg
  1513                                  	;
  1514                                          ;add    dword [scr_row], 0A0h
  1515                                          ;mov    edi, [scr_row]
  1516                                          ;
  1517                                  	;call 	printk
  1518                                  	;
  1519                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1520                                  	;out	20h, al	; 8259 PORT
  1521                                  	;
  1522                                  	;pop	es
  1523                                  	;pop	ds
  1524                                  	;pop	edi
  1525                                  	;pop	esi
  1526                                  	;pop 	eax
  1527                                  	;iret
  1528                                  	
  1529                                  	; 28/08/2015
  1530                                  	; 23/02/2015
  1531                                  	; 20/08/2014
  1532                                  ignore_int:
  1533 00000991 50                      	push	eax
  1534 00000992 53                      	push	ebx ; 23/02/2015
  1535 00000993 56                      	push	esi
  1536 00000994 57                      	push	edi
  1537 00000995 1E                      	push 	ds
  1538 00000996 06                      	push 	es
  1539                                  	; 28/08/2015
  1540 00000997 0F20D8                  	mov	eax, cr3
  1541 0000099A 50                      	push	eax ; (*) page directory
  1542                                  	;
  1543 0000099B B467                    	mov	ah, 67h	; brown (6) background, 
  1544                                  			; light gray (7) forecolor
  1545 0000099D BE[72660000]            	mov	esi, int_msg ; message offset
  1546                                  piemsg:
  1547                                          ; 27/08/2014
  1548 000009A2 8105[38660000]A000-             add     dword [scr_row], 0A0h
  1548 000009AA 0000               
  1549 000009AC 8B3D[38660000]                  mov     edi, [scr_row]
  1550                                          ;
  1551 000009B2 E8B7FCFFFF              	call 	printk
  1552                                  	;
  1553                                  	; 23/02/2015
  1554 000009B7 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1555 000009B9 E6A0                    	out	0A0h, al ; the 2nd 8259
  1556                                  iiretp: ; 01/09/2015
  1557                                  	; 28/08/2015
  1558 000009BB 58                      	pop	eax ; (*) page directory
  1559 000009BC 0F22D8                  	mov	cr3, eax
  1560                                  	;
  1561                                  iiret:
  1562                                  	; 22/08/2014
  1563 000009BF B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1564 000009C1 E620                    	out	20h, al	; 8259 PORT
  1565                                  	;
  1566 000009C3 07                      	pop	es
  1567 000009C4 1F                      	pop	ds
  1568 000009C5 5F                      	pop	edi
  1569 000009C6 5E                      	pop	esi
  1570 000009C7 5B                      	pop	ebx ; 29/08/2014
  1571 000009C8 58                      	pop 	eax
  1572 000009C9 CF                      	iretd
  1573                                  
  1574                                  	; 23/02/2022
  1575                                  	; 26/02/2015
  1576                                  	; 07/09/2014
  1577                                  	; 25/08/2014
  1578                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1579                                  	; 22/08/2014
  1580 000009CA 50                      	push	eax
  1581 000009CB 53                      	push	ebx ; 29/08/2014
  1582 000009CC 56                      	push	esi
  1583 000009CD 57                      	push	edi
  1584 000009CE 1E                      	push 	ds
  1585 000009CF 06                      	push 	es
  1586                                  	;
  1587 000009D0 B810000000              	mov	eax, KDATA
  1588 000009D5 8ED8                    	mov	ds, ax
  1589 000009D7 8EC0                    	mov	es, ax
  1590                                  	;
  1591                                  	; 25/08/2014
  1592                                  	;call	rtc_p
  1593                                  	; 23/02/2022
  1594 000009D9 FF15[2D070000]          	call	[x_rtci]
  1595                                  	;
  1596                                  	; 22/02/2015 - dsectpm.s
  1597                                  	; [ source: http://wiki.osdev.org/RTC ]
  1598                                  	; read status register C to complete procedure
  1599                                  	;(it is needed to get a next IRQ 8) 
  1600 000009DF B00C                    	mov	al, 0Ch ; 
  1601 000009E1 E670                    	out	70h, al ; select register C
  1602 000009E3 90                      	nop
  1603 000009E4 E471                    	in	al, 71h ; just throw away contents
  1604                                  	; 22/02/2015
  1605 000009E6 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1606 000009E8 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1607                                  	;
  1608 000009EA EBD3                    	jmp	short iiret	
  1609                                  
  1610                                  	; 22/08/2014
  1611                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1612                                  	; (INT 1Ah)
  1613                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1614                                  time_of_day:
  1615 000009EC E868010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1616 000009F1 726F                            jc      short rtc_retn 
  1617 000009F3 B000                    	mov	al, CMOS_SECONDS
  1618 000009F5 E847010000              	call	CMOS_READ
  1619 000009FA A2[5C6B0000]            	mov	[time_seconds], al 
  1620 000009FF B002                    	mov	al, CMOS_MINUTES
  1621 00000A01 E83B010000              	call	CMOS_READ
  1622 00000A06 A2[5D6B0000]            	mov	[time_minutes], al 
  1623 00000A0B B004                    	mov	al, CMOS_HOURS
  1624 00000A0D E82F010000              	call	CMOS_READ
  1625 00000A12 A2[5E6B0000]                    mov     [time_hours], al
  1626 00000A17 B006                    	mov	al, CMOS_DAY_WEEK 
  1627 00000A19 E823010000              	call	CMOS_READ
  1628 00000A1E A2[5F6B0000]            	mov	[date_wday], al
  1629 00000A23 B007                     	mov	al, CMOS_DAY_MONTH
  1630 00000A25 E817010000              	call	CMOS_READ
  1631 00000A2A A2[606B0000]            	mov	[date_day], al
  1632 00000A2F B008                    	mov	al, CMOS_MONTH
  1633 00000A31 E80B010000              	call	CMOS_READ
  1634 00000A36 A2[616B0000]            	mov	[date_month], al
  1635 00000A3B B009                    	mov	al, CMOS_YEAR
  1636 00000A3D E8FF000000              	call	CMOS_READ
  1637 00000A42 A2[626B0000]            	mov	[date_year], al
  1638 00000A47 B032                    	mov	al, CMOS_CENTURY
  1639 00000A49 E8F3000000              	call	CMOS_READ
  1640 00000A4E A2[636B0000]            	mov	[date_century], al
  1641                                  	;
  1642 00000A53 B000                    	mov	al, CMOS_SECONDS
  1643 00000A55 E8E7000000              	call 	CMOS_READ
  1644 00000A5A 3A05[5C6B0000]          	cmp	al, [time_seconds]
  1645 00000A60 758A                    	jne	short time_of_day
  1646                                  
  1647                                  rtc_retn:
  1648 00000A62 C3                      	retn
  1649                                  
  1650                                  rtci_default:
  1651                                  	; 23/02/2022 (Temporary!)
  1652                                  	; (default real time clock handler in multitasking mode)
  1653                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1654 00000A63 FF05[A46B0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1655                                  			; (not used in anywhere of kernel for now!)
  1656 00000A69 C3                      	retn
  1657                                  
  1658                                  rtc_p:	
  1659                                  	; 27/02/2022
  1660                                  	; 12/02/2022
  1661                                  	; 07/09/2014
  1662                                  	; 29/08/2014
  1663                                  	; 27/08/2014
  1664                                  	; 25/08/2014
  1665                                   	; Print Real Time Clock content
  1666                                  	;
  1667                                  	;
  1668 00000A6A E87DFFFFFF              	call	time_of_day
  1669 00000A6F 72F1                    	jc	short rtc_retn
  1670                                  	;
  1671 00000A71 3A05[26670000]          	cmp	al, [ptime_seconds]
  1672 00000A77 74E9                            je      short rtc_retn ; 29/08/2014
  1673                                  	;
  1674 00000A79 A2[26670000]            	mov	[ptime_seconds], al
  1675                                  	;
  1676 00000A7E A0[636B0000]            	mov	al, [date_century]
  1677 00000A83 E8EC000000              	call	bcd_to_ascii
  1678 00000A88 66A3[F3660000]          	mov	[datestr+6], ax
  1679 00000A8E A0[626B0000]            	mov	al, [date_year]
  1680 00000A93 E8DC000000              	call	bcd_to_ascii
  1681 00000A98 66A3[F5660000]          	mov	[datestr+8], ax
  1682 00000A9E A0[616B0000]            	mov	al, [date_month]
  1683 00000AA3 E8CC000000              	call	bcd_to_ascii
  1684 00000AA8 66A3[F0660000]          	mov	[datestr+3], ax
  1685 00000AAE A0[606B0000]            	mov	al, [date_day]
  1686 00000AB3 E8BC000000              	call	bcd_to_ascii
  1687 00000AB8 66A3[ED660000]          	mov	[datestr], ax
  1688                                  	;
  1689 00000ABE 0FB61D[5F6B0000]        	movzx	ebx, byte [date_wday]
  1690 00000AC5 C0E302                  	shl 	bl, 2
  1691 00000AC8 81C3[06670000]          	add	ebx, daytmp
  1692 00000ACE 8B03                    	mov	eax, [ebx]
  1693 00000AD0 A3[F8660000]            	mov	[daystr], eax
  1694                                  	;
  1695 00000AD5 A0[5E6B0000]            	mov	al, [time_hours]
  1696 00000ADA E895000000              	call	bcd_to_ascii
  1697 00000ADF 66A3[FC660000]          	mov	[timestr], ax
  1698 00000AE5 A0[5D6B0000]            	mov	al, [time_minutes]
  1699 00000AEA E885000000              	call	bcd_to_ascii
  1700 00000AEF 66A3[FF660000]          	mov	[timestr+3], ax
  1701 00000AF5 A0[5C6B0000]            	mov	al, [time_seconds]
  1702 00000AFA E875000000              	call	bcd_to_ascii
  1703 00000AFF 66A3[02670000]          	mov	[timestr+6], ax
  1704                                  	;		
  1705 00000B05 BE[DB660000]            	mov	esi, rtc_msg ; message offset
  1706                                  	; 23/02/2015
  1707 00000B0A 52                      	push	edx
  1708 00000B0B 51                      	push	ecx
  1709                                  	; 07/09/2014
  1710                                  	;mov	bx, 2	; Video page 2
  1711                                  	; 27/02/2022
  1712 00000B0C 29DB                    	sub	ebx, ebx
  1713 00000B0E B307                    	mov	bl, 7	; Video page 7
  1714                                  prtmsg:
  1715 00000B10 AC                      	lodsb
  1716 00000B11 08C0                    	or	al, al
  1717 00000B13 740D                    	jz	short prtmsg_ok
  1718 00000B15 56                      	push	esi
  1719                                  	; 27/02/2022
  1720 00000B16 53                      	push	ebx
  1721                                  	;push	bx
  1722 00000B17 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1723                                  			; white (F) forecolor
  1724 00000B19 E8C1080000              	call 	write_tty
  1725                                  	;pop	bx
  1726                                  	; 27/02/2022
  1727 00000B1E 5B                      	pop	ebx
  1728 00000B1F 5E                      	pop	esi
  1729 00000B20 EBEE                    	jmp	short prtmsg
  1730                                  	;
  1731                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1732                                  	;call	printk
  1733                                  prtmsg_ok:
  1734                                  	; 07/09/2014
  1735                                  	;xor	dx, dx		; column 0, row 0
  1736                                  	; 27/02/2022
  1737 00000B22 31D2                    	xor	edx, edx
  1738 00000B24 E8C0090000              	call	set_cpos	; set cursor position to 0,0 
  1739                                  	; 23/02/2015
  1740 00000B29 59                      	pop	ecx
  1741 00000B2A 5A                      	pop	edx
  1742 00000B2B C3                      	retn
  1743                                  
  1744                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1745                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1746                                  default_irq7:
  1747                                  	; 27/02/2022
  1748                                  	;push	ax
  1749 00000B2C 50                      	push	eax
  1750 00000B2D B00B                    	mov	al, 0Bh  ; In-Service register
  1751 00000B2F E620                    	out	20h, al
  1752 00000B31 EB00                            jmp short $+2
  1753 00000B33 EB00                    	jmp short $+2
  1754 00000B35 E420                    	in	al, 20h
  1755 00000B37 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1756 00000B39 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1757 00000B3B B020                            mov     al, 20h ; EOI
  1758 00000B3D E620                    	out	20h, al 
  1759                                  irq7_iret:
  1760                                  	;pop	ax
  1761                                  	; 27/02/2022
  1762 00000B3F 58                      	pop	eax
  1763 00000B40 CF                      	iretd
  1764                                  	
  1765                                  	; 22/08/2014
  1766                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1767                                  CMOS_READ:
  1768 00000B41 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1769 00000B42 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1770 00000B44 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1771 00000B45 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1772 00000B47 FA                      	cli		; DISABLE INTERRUPTS
  1773 00000B48 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1774 00000B4A 90                      	nop		; I/O DELAY
  1775 00000B4B E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1776 00000B4D 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1777                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1778                                  		     ; ----- 10/06/85 (test4.asm)
  1779 00000B4F B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1780                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1781 00000B51 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1782 00000B53 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1783 00000B55 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1784 00000B57 9D                      	popf	
  1785 00000B58 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1786                                  
  1787                                  	; 22/08/2014
  1788                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1789                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1790 00000B59 51                      	push	ecx
  1791 00000B5A B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1792                                  		; mov cx, 800	
  1793                                  UPD_10:
  1794 00000B5F B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1795 00000B61 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1796 00000B62 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1797 00000B67 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1798 00000B69 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1799 00000B6B FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1800 00000B6C E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1801 00000B6E 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1802                                  		; xor ax, ax
  1803 00000B70 F9                      	stc				; SET CARRY FOR ERROR
  1804                                  UPD_90:
  1805 00000B71 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1806 00000B72 FA                      	cli				; INTERRUPTS OFF DURING SET
  1807 00000B73 C3                      	retn				; RETURN WITH CY FLAG SET
  1808                                  
  1809                                  bcd_to_ascii:
  1810                                  	; 25/08/2014
  1811                                  	; INPUT ->
  1812                                  	;	al = Packed BCD number
  1813                                  	; OUTPUT ->
  1814                                  	;	ax  = ASCII word/number
  1815                                  	;
  1816                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1817                                  	;
  1818 00000B74 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1819                                  					; AH = AL / 10h
  1820                                  					; AL = AL MOD 10h
  1821 00000B76 660D3030                	or ax,'00'                      ; Make it ASCII based
  1822                                  
  1823 00000B7A 86E0                            xchg ah, al 
  1824                                  	
  1825 00000B7C C3                      	retn	
  1826                                  	
  1827                                  %include 'keyboard.inc' ; 07/03/2015
  1828                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1829                              <1> ; Last Modification: 23/02/2022
  1830                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1831                              <1> ;
  1832                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1833                              <1> 
  1834                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1835                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1836                              <1> ; 30/06/2015
  1837                              <1> ; 11/03/2015
  1838                              <1> ; 28/02/2015
  1839                              <1> ; 25/02/2015
  1840                              <1> ; 20/02/2015
  1841                              <1> ; 18/02/2015
  1842                              <1> ; 03/12/2014
  1843                              <1> ; 07/09/2014
  1844                              <1> ; KEYBOARD INTERRUPT HANDLER
  1845                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1846                              <1> 
  1847                              <1> ;getch:
  1848                              <1> ;	; 18/02/2015
  1849                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1850                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1851                              <1> ;	; routine, later... (multi tasking ability)
  1852                              <1> ;	; 28/02/2015
  1853                              <1> ;	sti	; enable interrupts
  1854                              <1> ;	;
  1855                              <1> ;	;push	esi
  1856                              <1> ;	;push	ebx
  1857                              <1> ;	;xor	ebx, ebx
  1858                              <1> ;	;mov	bl, [ptty]  ; active_page
  1859                              <1> ;	;mov	esi, ebx
  1860                              <1> ;	;shl 	si, 1
  1861                              <1> ;	;add	esi, ttychr
  1862                              <1> ;getch_1:
  1863                              <1> ;	;mov	ax, [esi]
  1864                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1865                              <1> ;	and	ax, ax
  1866                              <1> ;	jz	short getch_2
  1867                              <1> ;	mov	word [ttychr], 0
  1868                              <1> ;	;mov	word [esi], 0
  1869                              <1> ;	;pop	ebx
  1870                              <1> ;	;pop	esi
  1871                              <1> ;	retn
  1872                              <1> ;getch_2:
  1873                              <1> ;	hlt	; not proper for multi tasking!
  1874                              <1> ;		; (temporary halt for now)
  1875                              <1> ;		; 'sleep' on tty 
  1876                              <1> ;		; will (must) be located here		
  1877                              <1> ;	nop
  1878                              <1> ;	jmp	short getch_1
  1879                              <1> 
  1880                              <1> keyb_int:
  1881                              <1> 	; 23/02/2022
  1882                              <1> 	; 30/06/2015
  1883                              <1> 	; 25/02/2015
  1884                              <1> 	; 20/02/2015
  1885                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1886                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1887                              <1> 	; 30/06/2014
  1888                              <1> 	; 10/05/2013	
  1889                              <1>       	; Retro Unix 8086 v1 feature only!
  1890                              <1> 	; 03/03/2014
  1891                              <1> 	
  1892 00000B7D 1E                  <1> 	push	ds
  1893 00000B7E 53                  <1> 	push	ebx
  1894 00000B7F 50                  <1> 	push	eax
  1895                              <1> 	;
  1896                              <1> 	; 23/02/2022
  1897 00000B80 9C                  <1> 	pushfd
  1898 00000B81 0E                  <1> 	push	cs
  1899                              <1> 	;mov	ax, KDATA
  1900 00000B82 31C0                <1> 	xor	eax, eax
  1901 00000B84 B010                <1> 	mov	al, KDATA
  1902 00000B86 8ED8                <1> 	mov	ds, ax
  1903                              <1> 	;
  1904                              <1> 	;pushfd
  1905                              <1> 	;push	cs
  1906 00000B88 E810020000          <1> 	call	kb_int   ; int_09h
  1907                              <1> 	;
  1908 00000B8D B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1909                              <1> 	;call	getc
  1910 00000B8F E854000000          <1> 	call	int_16h  ; 30/06/2015
  1911 00000B94 744E                <1> 	jz	short keyb_int4
  1912                              <1> 	;
  1913 00000B96 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1914                              <1> 	;call	getc
  1915 00000B98 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1916                              <1> 	;
  1917                              <1> 	; 20/02/2015
  1918 00000B9D 0FB61D[166B0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1919                              <1> 	;
  1920 00000BA4 20C0                <1> 	and 	al, al
  1921 00000BA6 751D                <1> 	jnz	short keyb_int1
  1922                              <1> 	;
  1923 00000BA8 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1924 00000BAB 7218                <1> 	jb	short keyb_int1
  1925 00000BAD 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1926 00000BB0 7713                <1> 	ja	short keyb_int1
  1927                              <1> 	;
  1928 00000BB2 88D8                <1> 	mov	al, bl
  1929 00000BB4 0468                <1> 	add	al, 68h
  1930 00000BB6 38E0                <1> 	cmp	al, ah
  1931 00000BB8 7409                <1> 	je	short keyb_int0
  1932 00000BBA 88E0                <1> 	mov	al, ah
  1933 00000BBC 2C68                <1> 	sub	al, 68h
  1934 00000BBE E83F0A0000          <1> 	call	tty_sw
  1935                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1936                              <1> keyb_int0: ; 30/06/2015
  1937                              <1> 	;xor	ax, ax
  1938                              <1> 	; 23/02/2022
  1939 00000BC3 31C0                <1> 	xor	eax, eax
  1940                              <1> keyb_int1:
  1941 00000BC5 D0E3                <1> 	shl	bl, 1
  1942 00000BC7 81C3[186B0000]      <1> 	add	ebx, ttychr
  1943                              <1> 	;
  1944                              <1> 	;23/02/2022
  1945 00000BCD 09C0                <1> 	or	eax, eax
  1946                              <1> 	;or	ax, ax
  1947 00000BCF 7406                <1> 	jz	short keyb_int2
  1948                              <1> 	;
  1949 00000BD1 66833B00            <1> 	cmp 	word [ebx], 0
  1950 00000BD5 7703                <1>         ja      short keyb_int3 
  1951                              <1> keyb_int2:
  1952 00000BD7 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1953                              <1> 			   ; and scan code of the character
  1954                              <1> 			   ; for current tty (or last tty
  1955                              <1> 			   ; just before tty switch).
  1956                              <1> keyb_int3:
  1957 00000BDA A0[166B0000]        <1>         mov     al, [ptty]
  1958 00000BDF E8B1430000          <1> 	call	wakeup
  1959                              <1> 	;
  1960                              <1> keyb_int4:
  1961 00000BE4 58                  <1> 	pop	eax
  1962 00000BE5 5B                  <1> 	pop	ebx
  1963 00000BE6 1F                  <1> 	pop	ds
  1964 00000BE7 CF                  <1> 	iret
  1965                              <1> 
  1966                              <1> ; 18/02/2015
  1967                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1968                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1969                              <1> ; scancode and ascii code of the character 
  1970                              <1> ; in the tty input (ttychr) buffer. 
  1971                              <1> ; Test procedures must call 'getch' for tty input
  1972                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1973                              <1> ; due to infinite (key press) waiting loop.
  1974                              <1> ; 
  1975                              <1> ; 03/12/2014
  1976                              <1> ; 26/08/2014
  1977                              <1> ; KEYBOARD I/O
  1978                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1979                              <1> 
  1980                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1981                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1982                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1983                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1984                              <1> 
  1985                              <1> int_16h: ; 30/06/2015
  1986                              <1> ;getc:
  1987 00000BE8 9C                  <1> 	pushfd	; 28/08/2014
  1988 00000BE9 0E                  <1> 	push 	cs
  1989 00000BEA E826000000          <1> 	call 	getc_int
  1990 00000BEF C3                  <1> 	retn
  1991                              <1> 
  1992                              <1> ; 24/12/2021
  1993                              <1> 
  1994                              <1> 	;-----	SHIFT STATUS
  1995                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  1996 00000BF0 8A25[14650000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  1997 00000BF6 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  1998                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  1999                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2000 00000BF9 C0E405              <1>         shl	ah, 5
  2001 00000BFC A0[14650000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2002 00000C01 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2003 00000C03 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2004 00000C05 A0[16650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2005 00000C0A 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2006 00000C0C 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2007                              <1> _K3:
  2008 00000C0E A0[13650000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2009 00000C13 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2010                              <1> 
  2011                              <1> getc_int:
  2012                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2013                              <1> 	; 28/02/2015
  2014                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2015                              <1> 	;	      instead of pc-at bios - 1985-)
  2016                              <1> 	; 28/08/2014 (_k1d)
  2017                              <1> 	; 30/06/2014
  2018                              <1> 	; 03/03/2014
  2019                              <1> 	; 28/02/2014
  2020                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2021                              <1> 	; rombios source code (21/04/1986)
  2022                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2023                              <1> 	;
  2024                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2025                              <1> 	;
  2026                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2027                              <1> 	; KEYBOARD I/O								      :
  2028                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2029                              <1> 	; INPUT									      :
  2030                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2031                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2032                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2033                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2034                              <1> 	;-----------------------------------------------------------------------------:
  2035                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2036                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2037                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2038                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2039                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2040                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2041                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2042                              <1> 	;-----------------------------------------------------------------------------:	
  2043                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2044                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2045                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2046                              <1> 	;-----------------------------------------------------------------------------:	
  2047                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2048                              <1> 	;	      (AL) = 05H                                                      :
  2049                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2050                              <1> 	;		       							      :
  2051                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2052                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2053                              <1> 	;                     --------------------------------------------            :
  2054                              <1> 	;			00H        30.0        10H        7.5                 :
  2055                              <1> 	;			01H        26.7        11H        6.7                 :
  2056                              <1> 	;			02H        24.0        12H        6.0                 :
  2057                              <1> 	;			03H        21.8        13H        5.5                 :
  2058                              <1> 	;			04H        20.0        14H        5.0                 :
  2059                              <1> 	;			05H        18.5        15H        4.6                 :
  2060                              <1> 	;			06H        17.1        16H        4.3                 :
  2061                              <1> 	;			07H        16.0        17H        4.0                 :
  2062                              <1> 	;			08H        15.0        18H        3.7                 :
  2063                              <1> 	;			09H        13.3        19H        3.3                 :
  2064                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2065                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2066                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2067                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2068                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2069                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2070                              <1> 	;									      :
  2071                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2072                              <1> 	;		       							      :
  2073                              <1> 	;                     REGISTER     DELAY                                      :
  2074                              <1> 	;                      VALUE       VALUE                                      :
  2075                              <1> 	;                     ------------------                                      :
  2076                              <1> 	;			00H        250 ms                                     :
  2077                              <1> 	;			01H        500 ms                                     :
  2078                              <1> 	;			02H        750 ms                                     :
  2079                              <1> 	;			03H       1000 ms                                     :
  2080                              <1> 	;-----------------------------------------------------------------------------:
  2081                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2082                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2083                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2084                              <1> 	;		           (CH) = SCAN CODE                                   :
  2085                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2086                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2087                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2088                              <1> 	;-----------------------------------------------------------------------------:		
  2089                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2090                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2091                              <1> 	;-----------------------------------------------------------------------------:
  2092                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2093                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2094                              <1> 	;-----------------------------------------------------------------------------:	
  2095                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2096                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2097                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2098                              <1> 	; OUTPUT					                              :
  2099                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2100                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2101                              <1> 	;------------------------------------------------------------------------------
  2102                              <1> 	
  2103 00000C15 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2104 00000C16 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2105 00000C17 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2106                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2107 00000C18 66BB1000            <1>         mov     bx, KDATA 
  2108 00000C1C 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2109 00000C1E 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2110 00000C20 742D                <1> 	jz	short _K1		; ASCII_READ
  2111 00000C22 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2112 00000C24 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2113 00000C26 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2114 00000C28 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2115 00000C2A FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2116 00000C2C 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2117 00000C2E 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2118 00000C31 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2119                              <1> _KIO1:	
  2120 00000C33 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2121 00000C36 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2122 00000C38 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2123 00000C3A 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2124 00000C3C FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2125 00000C3E 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2126                              <1> _KIO_EXIT:
  2127                              <1> 	;pop	ecx			; RECOVER REGISTER
  2128 00000C40 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2129 00000C41 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2130 00000C42 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2131                              <1> 
  2132                              <1> 	;-----	ASCII CHARACTER
  2133                              <1> _K1E:	
  2134 00000C43 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2135 00000C48 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2136 00000C4D EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2137                              <1> _K1:	
  2138 00000C4F E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2139 00000C54 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2140 00000C59 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2141                              <1> _K1A:
  2142 00000C5B EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2143                              <1> 
  2144                              <1> 	;-----	ASCII STATUS
  2145                              <1> _K2E:	
  2146 00000C5D E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2147 00000C62 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2148 00000C64 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2149 00000C65 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2150 00000C6A EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2151                              <1> _K2:	
  2152 00000C6C E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2153 00000C71 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2154 00000C73 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2155 00000C74 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2156 00000C79 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2157 00000C7B 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2158 00000C7C E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2159 00000C81 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2160                              <1> _K2A:
  2161 00000C83 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2162                              <1> _K2B:
  2163                              <1> 	;pop	ecx			; RECOVER REGISTER
  2164 00000C84 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2165 00000C85 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2166 00000C86 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2167                              <1> 
  2168                              <1> ; 24/12/2021
  2169                              <1> ;	;-----	SHIFT STATUS
  2170                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2171                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2172                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2173                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2174                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2175                              <1> ;       shl	ah, 5
  2176                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2177                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2178                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2179                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2180                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2181                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2182                              <1> ;_K3:
  2183                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2184                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2185                              <1> 
  2186                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2187                              <1> _K300:
  2188 00000C89 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2189 00000C8B 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2190 00000C8D F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2191 00000C90 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2192 00000C92 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2193 00000C95 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2194 00000C97 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2195 00000C99 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2196                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2197                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2198 00000C9E C0E705              <1> 	shl	bh, 5
  2199 00000CA1 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2200 00000CA3 08F8                <1> 	or	al, bh			; AND DELAY
  2201 00000CA5 E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2202 00000CAA EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2203                              <1> 
  2204                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2205                              <1> _K500:
  2206 00000CAC 56                  <1> 	push	esi			; SAVE SI (esi)
  2207 00000CAD FA                  <1> 	cli				; 
  2208 00000CAE 8B1D[24650000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2209 00000CB4 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2210 00000CB6 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2211 00000CBB 3B1D[20650000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2212 00000CC1 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2213 00000CC3 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2214 00000CC6 891D[24650000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2215 00000CCC 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2216 00000CCE EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2217                              <1> _K502:
  2218 00000CD0 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2219                              <1> _K504:
  2220 00000CD2 FB                  <1> 	sti				
  2221 00000CD3 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2222 00000CD4 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2223                              <1> 
  2224                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2225                              <1> _K1S:
  2226 00000CD9 FA                  <1> 	cli	; 03/12/2014
  2227 00000CDA 8B1D[20650000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2228 00000CE0 3B1D[24650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2229                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2230 00000CE6 750F                <1> 	jne	short _k1x ; 03/12/2014
  2231                              <1> 	;
  2232                              <1> 	; 03/12/2014
  2233                              <1> 	; 28/08/2014
  2234                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2235                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2236                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2237                              <1> _K1T:                                   ; ASCII READ
  2238 00000CE8 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2239 00000CE9 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2240                              <1> _K1U:	
  2241 00000CEA FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2242 00000CEB 8B1D[20650000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2243 00000CF1 3B1D[24650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2244                              <1> _k1x:
  2245 00000CF7 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2246 00000CF8 9C                  <1> 	pushf				; SAVE FLAGS
  2247 00000CF9 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2248 00000CFE 8A1D[15650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2249 00000D04 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2250 00000D06 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2251 00000D09 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2252 00000D0B E86E060000          <1> 	call	SND_LED1
  2253 00000D10 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2254                              <1> _K1V:
  2255 00000D11 9D                  <1> 	popf				; RESTORE FLAGS
  2256 00000D12 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2257 00000D13 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2258                              <1> 	;
  2259 00000D15 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2260 00000D18 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2261 00000D1D 891D[20650000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2262 00000D23 C3                  <1> 	retn				; RETURN
  2263                              <1> 
  2264                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2265                              <1> _K2S:
  2266 00000D24 FA                  <1> 	cli				; INTERRUPTS OFF
  2267 00000D25 8B1D[20650000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2268 00000D2B 3B1D[24650000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2269 00000D31 668B03              <1> 	mov	ax, [ebx]
  2270 00000D34 9C                  <1> 	pushf				; SAVE FLAGS
  2271                              <1> 	;push	ax			; SAVE CODE
  2272                              <1> 	; 24/12/2021
  2273 00000D35 50                  <1> 	push	eax
  2274 00000D36 E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2275 00000D3B 8A1D[15650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2276 00000D41 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2277 00000D43 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2278 00000D46 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2279 00000D48 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2280                              <1> _K2T:
  2281                              <1> 	;pop	ax			; RESTORE CODE
  2282                              <1> 	; 24/12/2021
  2283 00000D4D 58                  <1> 	pop	eax
  2284 00000D4E 9D                  <1> 	popf				; RESTORE FLAGS
  2285 00000D4F FB                  <1> 	sti				; INTERRUPTS BACK ON
  2286 00000D50 C3                  <1> 	retn				; RETURN
  2287                              <1> 
  2288                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2289                              <1> _KIO_E_XLAT:
  2290 00000D51 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2291 00000D53 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2292 00000D55 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2293 00000D57 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2294 00000D59 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2295                              <1> _KIO_E_RET:				
  2296 00000D5B C3                  <1> 	retn				; GO BACK
  2297                              <1> 
  2298                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2299                              <1> _KIO_S_XLAT:
  2300 00000D5C 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2301 00000D5F 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2302 00000D61 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2303 00000D63 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2304 00000D65 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2305 00000D67 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2306 00000D69 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2307                              <1> _kio_ret: ; 03/12/2014
  2308 00000D6B F8                  <1> 	clc
  2309 00000D6C C3                  <1> 	retn
  2310                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2311                              <1> _KIO_S1:				
  2312 00000D6D B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2313                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2314 00000D6F C3                  <1> 	retn
  2315                              <1> _KIO_S2:		
  2316 00000D70 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2317 00000D73 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2318 00000D75 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2319 00000D77 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2320 00000D79 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2321 00000D7B 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2322 00000D7D EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2323                              <1> _KIO_S3:
  2324 00000D7F 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2325                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2326 00000D81 75E8                <1> 	jne	short _kio_ret
  2327 00000D83 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2328 00000D85 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2329 00000D87 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2330                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2331                              <1> _KIO_USE:
  2332                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2333 00000D89 C3                  <1> 	retn				; RETURN	
  2334                              <1> _KIO_DIS:
  2335 00000D8A F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2336 00000D8B C3                  <1> 	retn				; RETURN
  2337                              <1> 
  2338                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2339                              <1> _K4:    
  2340 00000D8C 43                  <1> 	inc     ebx
  2341 00000D8D 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2342 00000D8E 3B1D[1C650000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2343                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2344 00000D94 7206                <1> 	jb	short _K5
  2345 00000D96 8B1D[18650000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2346                              <1> _K5:
  2347 00000D9C C3                  <1> 	retn
  2348                              <1> 
  2349                              <1> ; 20/02/2015
  2350                              <1> ; 05/12/2014
  2351                              <1> ; 26/08/2014
  2352                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2353                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2354                              <1> ;
  2355                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2356                              <1> ; rombios source code (06/10/1985)
  2357                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2358                              <1> 
  2359                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2360                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2361                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2362                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2363                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2364                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2365                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2366                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2367                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2368                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2369                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2370                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2371                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2372                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2373                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2374                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2375                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2376                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2377                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2378                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2379                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2380                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2381                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2382                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2383                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2384                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2385                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2386                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2387                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2388                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2389                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2390                              <1> F11_M		equ	87		; F11 KEY MAKE
  2391                              <1> F12_M		equ	88		; F12 KEY MAKE
  2392                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2393                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2394                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2395                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2396                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2397                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2398                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2399                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2400                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2401                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2402                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2403                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2404                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2405                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2406                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2407                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2408                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2409                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2410                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2411                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2412                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2413                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2414                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2415                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2416                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2417                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2418                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2419                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2420                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2421                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2422                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2423                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2424                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2425                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2426                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2427                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2428                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2429                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2430                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2431                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2432                              <1> ;
  2433                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2434                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2435                              <1> INTA00		equ	020h		; 8259 PORT
  2436                              <1> 
  2437                              <1> 
  2438                              <1> kb_int:
  2439                              <1> 
  2440                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2441                              <1> ; 17/10/2015 ('ctrlbrk') 
  2442                              <1> ; 05/12/2014
  2443                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2444                              <1> 	;	      instead of pc-at bios - 1985-)
  2445                              <1> ; 26/08/2014
  2446                              <1> ;
  2447                              <1> ; 03/06/86  KEYBOARD BIOS
  2448                              <1> ;
  2449                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2450                              <1> ;										;
  2451                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2452                              <1> ;										;
  2453                              <1> ;--------------------------------------------------------------------------------
  2454                              <1> 
  2455                              <1> KB_INT_1:
  2456 00000D9D FB                  <1> 	sti				; ENABLE INTERRUPTS
  2457                              <1> 	;push	ebp
  2458 00000D9E 50                  <1> 	push	eax
  2459 00000D9F 53                  <1> 	push	ebx
  2460 00000DA0 51                  <1> 	push	ecx
  2461 00000DA1 52                  <1> 	push	edx
  2462 00000DA2 56                  <1> 	push	esi
  2463 00000DA3 57                  <1> 	push	edi
  2464 00000DA4 1E                  <1> 	push	ds
  2465 00000DA5 06                  <1> 	push	es
  2466 00000DA6 FC                  <1> 	cld				; FORWARD DIRECTION
  2467 00000DA7 66B81000            <1> 	mov	ax, KDATA
  2468 00000DAB 8ED8                <1> 	mov	ds, ax
  2469 00000DAD 8EC0                <1> 	mov	es, ax
  2470                              <1> 	;
  2471                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2472 00000DAF B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2473 00000DB1 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2474 00000DB6 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2475 00000DB7 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2476                              <1> KB_INT_01:
  2477 00000DBC E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2478 00000DBE A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2479 00000DC0 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2480                              <1> 	;
  2481                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2482 00000DC2 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2483                              <1> 	;
  2484                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2485                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2486                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2487                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2488                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2489                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2490                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2491                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2492                              <1> 	;
  2493                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2494                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2495 00000DC4 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2496 00000DC5 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2497 00000DC7 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2498                              <1> 	;
  2499                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2500 00000DC9 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2501 00000DCB 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2502                              <1> 	;
  2503                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2504 00000DCD FA                  <1> 	cli				; DISABLE INTERRUPTS
  2505 00000DCE 800D[15650000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2506 00000DD5 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2507                              <1> 	;
  2508                              <1> 	;-----	RESEND THE LAST BYTE
  2509                              <1> KB_INT_4:
  2510 00000DDA FA                  <1> 	cli				; DISABLE INTERRUPTS
  2511 00000DDB 800D[15650000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2512 00000DE2 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2513                              <1> 	;
  2514                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2515                              <1> KB_INT_2:
  2516                              <1> 	;push 	ax			; SAVE DATA IN
  2517                              <1> 	; 24/12/2021
  2518 00000DE7 50                  <1> 	push	eax
  2519 00000DE8 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2520 00000DED 8A1D[15650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2521 00000DF3 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2522 00000DF5 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2523 00000DF8 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2524 00000DFA E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2525                              <1> UP0:
  2526                              <1> 	;pop	ax			; RESTORE DATA IN
  2527                              <1> 	; 24/12/2021
  2528 00000DFF 58                  <1> 	pop	eax
  2529                              <1> ;------------------------------------------------------------------------
  2530                              <1> ;	START OF KEY PROCESSING						;
  2531                              <1> ;------------------------------------------------------------------------
  2532 00000E00 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2533                              <1> 	;
  2534                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2535 00000E02 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2536                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2537                              <1> 	; 24/12/2021
  2538 00000E04 7505                <1> 	jne	short K16
  2539 00000E06 E9ED040000          <1> 	jmp	K62
  2540                              <1> K16:	
  2541 00000E0B 8A3D[16650000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2542                              <1> 	;
  2543                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2544 00000E11 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2545 00000E14 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2546 00000E16 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2547 00000E18 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2548 00000E1A 7507                <1> 	jne	short RST_RD_ID
  2549 00000E1C 800D[16650000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2550                              <1> RST_RD_ID:
  2551 00000E23 8025[16650000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2552 00000E2A EB27                <1>         jmp    short ID_EX		; AND EXIT
  2553                              <1> 	; 24/12/2021
  2554                              <1> 	;jmp	K26
  2555                              <1> 	;
  2556                              <1> TST_ID_2:
  2557 00000E2C 8025[16650000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2558 00000E33 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2559 00000E35 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2560 00000E37 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2561 00000E39 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2562                              <1> 	; 24/12/2021
  2563                              <1> 	;jne	K26
  2564                              <1> 	;
  2565                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2566 00000E3B F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2567 00000E3E 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2568 00000E40 800D[13650000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2569 00000E47 E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2570                              <1> KX_BIT:
  2571 00000E4C 800D[16650000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2572 00000E53 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2573                              <1> 	;
  2574                              <1> NOT_ID:
  2575 00000E58 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2576 00000E5A 750E                <1> 	jne	short TEST_E1
  2577 00000E5C 800D[16650000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2578 00000E63 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2579                              <1> 	; 24/12/2021
  2580 00000E65 E9DA010000          <1> 	jmp	K26A	
  2581                              <1> TEST_E1:	
  2582 00000E6A 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2583 00000E6C 750C                <1> 	jne	short NOT_HC
  2584 00000E6E 800D[16650000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2585 00000E75 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2586                              <1> 	;
  2587                              <1> NOT_HC:
  2588 00000E7A 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2589 00000E7C F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2590 00000E7F 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2591                              <1> 	;
  2592 00000E81 BF[FE630000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2593 00000E86 AE                  <1> 	scasb
  2594                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2595                              <1> 	; 24/12/2021
  2596 00000E87 7458                <1> 	je	short K16B
  2597 00000E89 AE                  <1> 	scasb
  2598 00000E8A 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2599 00000E8C EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2600                              <1> 	; 24/12/2021
  2601                              <1> 	;jmp	K26
  2602                              <1> 	;
  2603                              <1> NOT_LC_E0:
  2604 00000E8E F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2605 00000E91 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2606 00000E93 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2607 00000E98 BF[FC630000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2608 00000E9D F2AE                <1> 	repne	scasb			; CHECK IT
  2609 00000E9F 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2610                              <1> 	; 24/12/2021
  2611                              <1> 	;je	K26A			
  2612                              <1> 	;
  2613 00000EA1 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2614 00000EA3 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2615                              <1> 	; 24/12/2021
  2616                              <1> 	;jne	K26
  2617 00000EA5 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2618 00000EA8 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2619                              <1> 	; 24/12/2021
  2620                              <1> 	;jnz	K26
  2621                              <1>         ; 20/02/2015 
  2622 00000EAA F605[14650000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2623 00000EB1 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2624                              <1> 	; 24/12/2021
  2625                              <1> 	;jnz	K26
  2626 00000EB3 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2627                              <1> 	;
  2628                              <1> 	;-----	TEST FOR SYSTEM KEY
  2629                              <1> T_SYS_KEY:
  2630 00000EB8 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2631 00000EBA 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2632                              <1> 	;
  2633 00000EBC F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2634 00000EBF 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2635                              <1> 	;
  2636 00000EC1 F605[14650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2637 00000EC8 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2638                              <1> 	;jnz	K26			
  2639                              <1> 	;
  2640 00000ECA 800D[14650000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2641 00000ED1 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2642 00000ED3 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2643                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2644 00000ED5 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2645 00000ED7 E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2646                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2647                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2648                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2649                              <1> 	;INT	15H			; USER INTERRUPT	
  2650 00000EDC E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2651                              <1> 	;
  2652 00000EE1 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2653                              <1> 	;
  2654                              <1> K16C:
  2655 00000EE6 8025[14650000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2656 00000EED B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2657 00000EEF E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2658                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2659                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2660                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2661                              <1> 	;
  2662                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2663                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2664                              <1> 	;INT	15H			; USER INTERRUPT
  2665                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2666                              <1> 	;
  2667 00000EF1 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2668                              <1> 	;
  2669                              <1> 	;-----	TEST FOR SHIFT KEYS
  2670                              <1> K16A:
  2671 00000EF6 8A1D[13650000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2672 00000EFC BF[F8630000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2673 00000F01 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2674 00000F06 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2675 00000F08 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2676                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2677                              <1> 	; 24/12/2021
  2678 00000F0A 7405                <1> 	je	short K17
  2679 00000F0C E914010000          <1> 	jmp	K25
  2680                              <1> 	;
  2681                              <1> 	;------	SHIFT KEY FOUND
  2682                              <1> K17:
  2683 00000F11 81EF[F9630000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2684 00000F17 8AA7[00640000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2685 00000F1D B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2686 00000F1F A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2687                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2688                              <1> 	; 24/12/2021
  2689 00000F21 7405                <1> 	jz	short K17C
  2690 00000F23 E999000000          <1> 	jmp	K23
  2691                              <1> 	;
  2692                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2693                              <1> K17C:
  2694 00000F28 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2695 00000F2B 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2696                              <1> 	;
  2697                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2698 00000F2D 0825[13650000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2699 00000F33 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2700 00000F35 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2701                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2702                              <1> 	; 24/12/2021
  2703 00000F37 E901010000          <1> 	jmp	K26
  2704                              <1> K17D:
  2705 00000F3C F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2706 00000F3F 740B                <1> 	jz 	short K17E		; NO, JUMP
  2707 00000F41 0825[16650000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2708 00000F47 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2709                              <1> K17E:
  2710 00000F4C D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2711 00000F4E 0825[14650000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2712 00000F54 E9E4000000          <1> 	jmp	K26
  2713                              <1> 	;
  2714                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2715                              <1> K18:					; SHIFT-TOGGLE
  2716 00000F59 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2717 00000F5C 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2718                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2719                              <1> 	; 24/12/2021
  2720 00000F5E E9C2000000          <1> 	jmp	K25
  2721                              <1> K18A:
  2722 00000F63 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2723 00000F65 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2724 00000F67 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2725 00000F6A 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2726                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2727                              <1> 	; 24/12/2021
  2728 00000F6C E9B4000000          <1> 	jmp	K25
  2729                              <1> K18B:
  2730 00000F71 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2731 00000F74 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2732                              <1> K19:	
  2733 00000F76 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2734 00000F79 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2735 00000F7B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2736 00000F7E 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2737                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2738 00000F80 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2739 00000F82 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2740                              <1> K21:					; MIGHT BE NUMERIC
  2741 00000F87 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2742 00000F8A 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2743                              <1> 	;
  2744                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2745 00000F8C 8425[14650000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2746                              <1> 	;jnz	K26
  2747                              <1> 	; 24/12/2021
  2748 00000F92 7405                <1> 	jz	short K22A
  2749 00000F94 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2750                              <1> K22A:
  2751 00000F99 0825[14650000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2752 00000F9F 3025[13650000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2753                              <1> 	;
  2754                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2755 00000FA5 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2756 00000FA8 7407                <1> 	jz	short K22B		; GO IF NOT
  2757                              <1> 	;
  2758                              <1> 	; 24/12/2021
  2759                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2760 00000FAA 50                  <1> 	push	eax
  2761 00000FAB E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2762                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2763 00000FB0 58                  <1> 	pop	eax
  2764                              <1> K22B:
  2765 00000FB1 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2766                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2767                              <1> 	; 24/12/2021
  2768 00000FB3 7405                <1> 	je	short K22C
  2769 00000FB5 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2770                              <1> K22C:
  2771 00000FBA 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2772 00000FBC E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2773                              <1> 	;
  2774                              <1> 	;-----	BREAK SHIFT FOUND
  2775                              <1> K23:					; BREAK-SHIFT-FOUND
  2776 00000FC1 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2777 00000FC4 F6D4                <1> 	not	ah			; INVERT MASK
  2778 00000FC6 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2779 00000FC8 2025[13650000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2780 00000FCE 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2781 00000FD1 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2782                              <1> 	;
  2783 00000FD3 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2784 00000FD6 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2785 00000FD8 2025[16650000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2786 00000FDE EB08                <1> 	jmp	short K23B		; CONTINUE
  2787                              <1> K23A:
  2788 00000FE0 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2789 00000FE2 2025[14650000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2790                              <1> K23B:
  2791 00000FE8 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2792 00000FEA A0[16650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2793 00000FEF D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2794 00000FF1 0A05[14650000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2795 00000FF7 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2796 00000FF9 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2797 00000FFB 0805[13650000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2798 00001001 88E0                <1> 	mov	al, ah
  2799                              <1> K23D:
  2800 00001003 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2801 00001005 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2802                              <1> 	;	
  2803                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2804 00001007 A0[17650000]        <1> 	mov	al, [ALT_INPUT]
  2805 0000100C B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2806 0000100E 8825[17650000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2807 00001014 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2808 00001016 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2809 00001018 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2810                              <1> 	;
  2811                              <1> K24:					; BREAK-TOGGLE
  2812 0000101D 2025[14650000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2813 00001023 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2814                              <1> 	;
  2815                              <1> 	;-----	TEST FOR HOLD STATE
  2816                              <1> 					; AL, AH = SCAN CODE
  2817                              <1> K25:					; NO-SHIFT-FOUND
  2818 00001025 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2819 00001027 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2820 00001029 F605[14650000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2821 00001030 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2822 00001032 3C45                <1> 	cmp	al, NUM_KEY
  2823 00001034 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2824 00001036 8025[14650000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2825                              <1> 	;
  2826                              <1> K26:
  2827 0000103D 8025[16650000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2828                              <1> K26A:					; INTERRUPT-RETURN
  2829 00001044 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2830 00001045 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2831 00001047 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2832                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2833 00001049 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2834 0000104B E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2835                              <1> K27A:
  2836 00001050 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2837 00001051 07                  <1> 	pop	es			; RESTORE REGISTERS
  2838 00001052 1F                  <1> 	pop	ds
  2839 00001053 5F                  <1> 	pop	edi
  2840 00001054 5E                  <1> 	pop	esi
  2841 00001055 5A                  <1> 	pop	edx
  2842 00001056 59                  <1> 	pop	ecx
  2843 00001057 5B                  <1> 	pop	ebx
  2844 00001058 58                  <1> 	pop	eax
  2845                              <1> 	;pop	ebp
  2846 00001059 CF                  <1> 	iret				; RETURN
  2847                              <1> 
  2848                              <1> 	;-----	NOT IN	HOLD STATE
  2849                              <1> K28:					; NO-HOLD-STATE
  2850 0000105A 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2851 0000105C 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2852                              <1> 	;
  2853 0000105E F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2854 00001061 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2855                              <1>         ; 24/12/2021
  2856                              <1> 	;jz      K38
  2857                              <1> 	;
  2858 00001063 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2859 00001066 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2860                              <1> 	; 28/02/2015
  2861 00001068 F605[14650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2862 0000106F 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2863                              <1> 	; 24/12/2021
  2864                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2865                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2866 00001071 E9D1000000          <1> K28A:	jmp	K38
  2867                              <1> 	;
  2868                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2869                              <1> K29:					; TEST-RESET
  2870 00001076 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2871 00001079 740B                <1> 	jz	short K31		; NO_RESET
  2872 0000107B 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2873 0000107D 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2874                              <1> 	;
  2875                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2876                              <1>  	; 26/08/2014
  2877                              <1> cpu_reset:
  2878                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2879                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2880 0000107F B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2881 00001081 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2882                              <1> khere:
  2883 00001083 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2884 00001084 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2885                              <1> 
  2886                              <1> 	;
  2887                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2888                              <1> K31:					; NO-RESET
  2889 00001086 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2890 00001088 7507                <1> 	jne	short K311		; NOT THERE
  2891 0000108A B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2892 0000108C E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2893                              <1> K311:
  2894 00001091 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2895 00001093 7509                <1> 	jne	short K312		; NOT THERE
  2896 00001095 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2897 00001099 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2898                              <1> K312:
  2899 0000109E 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2900 000010A0 7471                <1>         je	short K37B              ; GO PROCESS
  2901 000010A2 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2902 000010A4 746D                <1>         je	short K37B              ; GO PROCESS
  2903                              <1> 	;
  2904                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2905                              <1> K32:					; ALT-KEY-PAD
  2906 000010A6 BF[D4630000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2907 000010AB B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2908 000010B0 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2909 000010B2 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2910 000010B4 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2911                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2912                              <1> 	; 24/12/2021
  2913 000010B7 751C                <1> 	jnz	short K32B
  2914 000010B9 81EF[D5630000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2915 000010BF A0[17650000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2916 000010C4 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2917 000010C6 F6E4                <1> 	mul	ah
  2918 000010C8 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2919 000010CB A2[17650000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2920                              <1> K32A:
  2921 000010D0 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2922                              <1> K32B:
  2923                              <1> 	; 24/12/2021
  2924 000010D5 EB6A                <1> 	jmp	K37C
  2925                              <1> 	;
  2926                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2927                              <1> K33:					; NO-ALT-KEYPAD
  2928 000010D7 C605[17650000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2929 000010DE B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2930 000010E3 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2931 000010E5 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2932                              <1> 	;
  2933                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2934                              <1> K34:					; ALT-TOP-ROW
  2935 000010E7 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2936 000010E9 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2937 000010EB 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2938 000010ED 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2939 000010EF 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2940 000010F2 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2941                              <1> 	;
  2942                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2943                              <1> K35:					; ALT-FUNCTION
  2944 000010F4 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2945 000010F6 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2946 000010F8 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2947 000010FA 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2948 000010FC 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2949 000010FF EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2950                              <1> K35A:
  2951 00001101 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2952 00001104 7425                <1> 	jz	short K37		; NO, JUMP
  2953 00001106 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2954 00001108 7510                <1>         jne     short K35B              ; NOT THERE
  2955 0000110A 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2956 0000110E E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2957                              <1> K37B:
  2958 00001113 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2959 00001115 E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2960                              <1> K35B:
  2961 0000111A 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2962 0000111C 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2963 0000111E 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2964 00001120 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2965                              <1>         ; 24/12/2021
  2966                              <1> 	;jne	K26
  2967 00001122 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2968 00001126 E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2969                              <1> K37:
  2970 0000112B 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2971 0000112D 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2972 0000112F 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2973                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2974 00001131 0F8706FFFFFF        <1>         ja      K26
  2975 00001137 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2976                              <1> K37A:
  2977 0000113A B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2978 0000113C E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2979                              <1> K37C:
  2980 00001141 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2981 00001143 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2982 00001145 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2983                              <1> 	;
  2984                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2985                              <1> K38:					; NOT-ALT-SHIFT
  2986                              <1> 					; BL STILL HAS SHIFT FLAGS
  2987 00001147 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2988 0000114A 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2989                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2990                              <1> 	; 24/12/2021
  2991 0000114C E9AB000000          <1> 	jmp	K44
  2992                              <1> 	;
  2993                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  2994                              <1> 	;-----	TEST FOR BREAK
  2995                              <1> K38A:
  2996 00001151 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  2997 00001153 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  2998 00001155 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2999 00001158 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3000 0000115A F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3001 0000115D 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3002                              <1> K38B:
  3003 0000115F 8B1D[20650000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3004 00001165 891D[24650000]      <1> 	mov	[BUFFER_TAIL], ebx
  3005 0000116B C605[12650000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3006                              <1> 	;
  3007                              <1> 	;-----	ENABLE KEYBOARD
  3008 00001172 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3009 00001174 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3010                              <1> 	;
  3011                              <1> 	; CTRL+BREAK code here !!!
  3012                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3013                              <1> 	; 17/10/2015	
  3014 00001179 E856220000          <1> 	call	ctrlbrk ; control+break subroutine
  3015                              <1> 	;
  3016                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3017                              <1> 	; 24/12/2021
  3018 0000117E 29C0                <1> 	sub	eax, eax
  3019 00001180 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3020                              <1> 	;
  3021                              <1> 	;-----	TEST FOR PAUSE
  3022                              <1> K39:					; NO_BREAK
  3023 00001185 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3024 00001188 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3025 0000118A 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3026 0000118C 7533                <1> 	jne	short K41		; NO-PAUSE
  3027                              <1> K39P:
  3028 0000118E 800D[14650000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3029                              <1> 	;
  3030                              <1> 	;-----	ENABLE KEYBOARD
  3031 00001195 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3032 00001197 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3033                              <1> K39A:
  3034 0000119C B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3035 0000119E E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3036                              <1> 	;
  3037                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3038 000011A0 803D[10650000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3039 000011A7 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3040 000011A9 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3041 000011AD A0[11650000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3042 000011B2 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3043                              <1> 	;
  3044                              <1> K40:					; PAUSE-LOOP
  3045 000011B3 F605[14650000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3046 000011BA 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3047                              <1> 	;
  3048 000011BC E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3049                              <1>         ;
  3050                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3051                              <1> K41:					; NO-PAUSE
  3052 000011C1 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3053 000011C3 7513                <1> 	jne	short K42		; NOT-KEY-55
  3054 000011C5 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3055 000011C8 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3056 000011CA F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3057 000011CD 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3058                              <1> K41A:	
  3059 000011CF 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3060 000011D3 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3061                              <1> 	;
  3062                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3063                              <1> K42:					; NOT-KEY-55
  3064 000011D8 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3065 000011DA 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3066 000011DC 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3067 000011DE 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3068 000011E0 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3069 000011E3 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3070 000011E5 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3071 000011E9 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3072                              <1> K42A:
  3073                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3074 000011EE 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3075                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3076                              <1> 	;;jb	K56 ; 20/02/2015
  3077                              <1> 	;;jmp	K64 ; 20/02/2015
  3078                              <1> K42B:
  3079 000011F0 BB[08640000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3080                              <1> 	;;jmp	K64
  3081                              <1> 	;jb	K56 ;; 20/02/2015	
  3082                              <1> 	; 24/12/2021
  3083 000011F5 7267                <1> 	jb	short K45F
  3084 000011F7 E9B9000000          <1> 	jmp	K64	
  3085                              <1>         ;
  3086                              <1> 	;-----	NOT IN CONTROL SHIFT
  3087                              <1> K44:					; NOT-CTL-SHIFT
  3088 000011FC 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3089 000011FE 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3090 00001200 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3091 00001203 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3092 00001205 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3093 00001208 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3094 0000120A EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3095                              <1> K44A:
  3096 0000120C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3097 0000120F 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3098                              <1> 	;
  3099                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3100                              <1> K44B:
  3101 00001211 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3102 00001213 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3103 00001218 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3104 0000121A E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3105                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3106                              <1> 	;PUSH 	BP			; SAVE POINTER
  3107                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3108                              <1> 	;POP	BP			; RESTORE POINTER
  3109 0000121C 8025[16650000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3110 00001223 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3111                              <1> 	;
  3112                              <1> 	;-----	HANDLE IN-CORE KEYS
  3113                              <1> K45:					; NOT-PRINT-SCREEN
  3114 00001228 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3115 0000122A 7734                <1> 	ja	short K46		; JUMP IF NOT
  3116 0000122C 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3117 0000122E 7505                <1> 	jne	short K45A		; NO, JUMP
  3118 00001230 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3119 00001233 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3120                              <1> K45A:
  3121 00001235 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3122 0000123A BF[DE630000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3123 0000123F F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3124                              <1> 		; 20/02/2015
  3125 00001241 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3126                              <1> 	;
  3127 00001243 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3128 00001246 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3129                              <1> K45B:
  3130 00001248 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3131 0000124B 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3132                              <1> 					; NO, LOWERCASE
  3133                              <1> K45C:
  3134 0000124D BB[60640000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3135 00001252 EB51                <1> 	jmp	short K56	
  3136                              <1> K45D:					; ALMOST-CAPS-STATE
  3137 00001254 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3138 00001257 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3139                              <1> K45E:
  3140 00001259 BB[B8640000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3141 0000125E EB45                <1> K45F:	jmp	short K56
  3142                              <1> 	;
  3143                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3144                              <1> K46:					; NOT IN-CORE AREA
  3145 00001260 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3146                              <1> 	;ja	short K47		; JUMP IF NOT
  3147                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3148 00001262 7635                <1> 	jna	short K53		
  3149                              <1> 	;
  3150                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3151                              <1> K47:					; NOT F1 - F10
  3152 00001264 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3153 00001266 772D                <1> 	ja	short K52		; JUMP IF NOT
  3154                              <1> 	;
  3155                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3156                              <1> K48:
  3157 00001268 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3158 0000126A 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3159 0000126C 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3160 0000126E 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3161 00001270 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3162 00001273 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3163                              <1> 	;		
  3164 00001275 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3165 00001278 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3166 0000127A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3167                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3168 0000127D 75DA                <1> 	jnz	short K45E
  3169                              <1> 	;
  3170                              <1> 	;-----	BASE CASE FOR KEYPAD
  3171                              <1> K49:					
  3172 0000127F 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3173 00001281 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3174 00001283 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3175 00001285 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3176                              <1> K49A:
  3177 00001287 BB[60640000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3178 0000128C EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3179                              <1> 	;
  3180                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3181                              <1> K50:					; ALMOST-NUM-STATE
  3182 0000128E F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3183 00001291 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3184 00001293 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3185                              <1> 	;
  3186                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3187                              <1> K52:					; NOT A NUMPAD KEY
  3188 00001295 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3189                              <1> 	;jne	short K53		; JUMP IF NOT
  3190                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3191 00001297 74AF                <1> 	je	short K45B		
  3192                              <1> 	;
  3193                              <1> 	;-----	MUST BE F11 OR F12 
  3194                              <1> K53:					; F1 - F10 COME HERE, TOO
  3195 00001299 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3196 0000129C 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3197                              <1> 		; 20/02/2015 
  3198 0000129E BB[B8640000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3199 000012A3 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3200                              <1> 	;
  3201                              <1> 	;-----	TRANSLATE THE CHARACTER
  3202                              <1> K56:					; TRANSLATE-CHAR
  3203 000012A5 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3204 000012A7 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3205 000012A8 F605[16650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3206 000012AF 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3207 000012B1 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3208 000012B3 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3209                              <1> 	;
  3210                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3211                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3212 000012B5 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3213 000012B7 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3214 000012B8 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3215 000012BA B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3216 000012BC F605[16650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3217 000012C3 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3218 000012C5 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3219                              <1> 	;
  3220                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3221                              <1> K57:					; BUFFER_FILL
  3222 000012C7 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3223 000012C9 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3224                              <1> 	; 24/12/2021
  3225                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3226 000012CB 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3227                              <1> 	; 24/12/2021
  3228 000012CE 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3229                              <1> 	;je	K26			; INTERRUPT_RETURN
  3230                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3231 000012D0 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3232                              <1> K61:					; NOT-CAPS-STATE
  3233 000012D5 8B1D[24650000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3234 000012DB 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3235 000012DD E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3236 000012E2 3B1D[20650000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3237 000012E8 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3238 000012EA 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3239 000012ED 891D[24650000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3240 000012F3 E945FDFFFF          <1> 	jmp	K26
  3241                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3242                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3243                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3244                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3245                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3246                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3247                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3248                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3249                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3250                              <1> 	;;jmp   K27                    
  3251                              <1> 	;
  3252                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3253                              <1> K62:
  3254 000012F8 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3255 000012FA E620                <1> 	out	INTA00, al
  3256 000012FC 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3257 00001300 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3258 00001302 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3259 00001307 E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3260                              <1> 
  3261                              <1> SHIP_IT:
  3262                              <1> 	;---------------------------------------------------------------------------------
  3263                              <1> 	; SHIP_IT
  3264                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3265                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3266                              <1> 	;---------------------------------------------------------------------------------
  3267                              <1> 	;
  3268                              <1> 	;push	ax			; SAVE DATA TO SEND
  3269                              <1> 	; 24/12/2021
  3270 0000130C 50                  <1> 	push	eax
  3271                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3272 0000130D FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3273                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3274 0000130E B900000100          <1> 	mov	ecx, 10000h			
  3275                              <1> S10:
  3276 00001313 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3277 00001315 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3278 00001317 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3279                              <1> 
  3280                              <1> 	;pop	ax			; GET DATA TO SEND
  3281                              <1> 	; 24/12/2021
  3282 00001319 58                  <1> 	pop	eax
  3283 0000131A E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3284 0000131C FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3285 0000131D C3                  <1> 	retn				; RETURN TO CALLER
  3286                              <1> 
  3287                              <1> SND_DATA:
  3288                              <1> 	; ---------------------------------------------------------------------------------
  3289                              <1> 	; SND_DATA
  3290                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3291                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3292                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3293                              <1> 	; ---------------------------------------------------------------------------------
  3294                              <1> 	;
  3295                              <1> 	;push	ax			; SAVE REGISTERS
  3296                              <1> 	;push	bx
  3297                              <1> 	; 24/12/2021
  3298 0000131E 50                  <1> 	push	eax
  3299 0000131F 53                  <1> 	push	ebx
  3300 00001320 51                  <1> 	push	ecx
  3301 00001321 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3302 00001323 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3303                              <1> SD0:
  3304 00001325 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3305 00001326 8025[15650000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3306                              <1> 	;
  3307                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3308 0000132D B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3309                              <1> SD5:
  3310 00001332 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3311 00001334 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3312 00001336 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3313                              <1> 	;
  3314 00001338 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3315 0000133A E660                <1> 	out	PORT_A, al		; SEND BYTE
  3316 0000133C FB                  <1> 	sti				; ENABLE INTERRUPTS
  3317                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3318 0000133D B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3319                              <1> SD1:
  3320 00001342 F605[15650000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3321 00001349 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3322 0000134B E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3323                              <1> SD2:
  3324 0000134D FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3325 0000134F 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3326 00001351 800D[15650000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3327 00001358 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3328                              <1> SD3:
  3329 0000135A F605[15650000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3330 00001361 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3331                              <1> SD4:	
  3332 00001363 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3333                              <1> 	;pop	bx
  3334                              <1> 	;pop	ax
  3335                              <1> 	; 24/12/2021
  3336 00001364 5B                  <1> 	pop	ebx
  3337 00001365 58                  <1> 	pop	eax
  3338 00001366 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3339                              <1> 
  3340                              <1> SND_LED:
  3341                              <1> 	; ---------------------------------------------------------------------------------
  3342                              <1> 	; SND_LED
  3343                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3344                              <1> 	;
  3345                              <1> 	;----------------------------------------------------------------------------------
  3346                              <1> 	;
  3347 00001367 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3348 00001368 F605[15650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3349 0000136F 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3350                              <1> 	;
  3351 00001371 800D[15650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3352 00001378 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3353 0000137A E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3354 0000137C EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3355                              <1> SND_LED1:
  3356 0000137E FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3357 0000137F F605[15650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3358 00001386 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3359                              <1> 	;
  3360 00001388 800D[15650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3361                              <1> SL0:
  3362 0000138F B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3363 00001391 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3364 00001396 FA                  <1> 	cli
  3365 00001397 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3366 0000139C 8025[15650000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3367 000013A3 0805[15650000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3368 000013A9 F605[15650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3369 000013B0 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3370                              <1> 	;
  3371 000013B2 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3372 000013B7 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3373 000013B8 F605[15650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3374 000013BF 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3375                              <1> SL2:
  3376 000013C1 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3377 000013C3 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3378 000013C8 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3379                              <1> SL3:
  3380 000013C9 8025[15650000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3381                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3382 000013D0 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3383 000013D1 C3                  <1> 	retn				; RETURN TO CALLER
  3384                              <1> 
  3385                              <1> MAKE_LED:
  3386                              <1> 	;---------------------------------------------------------------------------------
  3387                              <1> 	; MAKE_LED
  3388                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3389                              <1> 	;	THE MODE INDICATORS.
  3390                              <1> 	;---------------------------------------------------------------------------------
  3391                              <1> 	;
  3392                              <1> 	;push 	cx			; SAVE CX
  3393 000013D2 A0[13650000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3394 000013D7 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3395                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3396                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3397 000013D9 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3398 000013DC 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3399                              <1> 	;pop	cx
  3400 000013DE C3                  <1> 	retn				; RETURN TO CALLER
  3401                              <1> 
  3402                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3403                              <1> 
  3404                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1828                                  
  1829                                  %include 'video.inc' ; 07/03/2015
  1830                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1831                              <1> ; Last Modification: 25/02/2022
  1832                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1833                              <1> ;
  1834                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1835                              <1> 
  1836                              <1> ; 02/02/2022 (simplified scroll up)
  1837                              <1> ; 16/01/2016
  1838                              <1> ; 30/06/2015
  1839                              <1> ; 27/06/2015
  1840                              <1> ; 11/03/2015
  1841                              <1> ; 02/09/2014
  1842                              <1> ; 30/08/2014
  1843                              <1> ; VIDEO FUNCTIONS
  1844                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1845                              <1> 
  1846                              <1> write_tty:
  1847                              <1> 	; 02/02/2022
  1848                              <1> 	; 13/08/2015
  1849                              <1> 	; 02/09/2014
  1850                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1851                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1852                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1853                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1854                              <1> 	;
  1855                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1856                              <1> 	;	   AL = Character to be written
  1857                              <1> 	;	   EBX = Video Page (0 to 7)
  1858                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1859                              <1> 
  1860                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1861                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1862                              <1> 
  1863                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1864                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1865                              <1> ;
  1866                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1867                              <1> ;
  1868                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1869                              <1> ;										:
  1870                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1871                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1872                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1873                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1874                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1875                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1876                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1877                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1878                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1879                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1880                              <1> ;   THE 0 COLOR IS USED.							:
  1881                              <1> ;   ENTRY --									:
  1882                              <1> ;     (AH) = CURRENT CRT MODE							:
  1883                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1884                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1885                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1886                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1887                              <1> ;   EXIT -- 									:
  1888                              <1> ;     ALL REGISTERS SAVED							:
  1889                              <1> ;--------------------------------------------------------------------------------
  1890                              <1> 
  1891 000013DF FA                  <1> 	cli
  1892                              <1> 	;
  1893                              <1> 	; READ CURSOR (04/12/2013)
  1894                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1895 000013E0 08FF                <1> 	or	bh, bh
  1896                              <1> 	;jnz	beeper
  1897                              <1> 	; 02/02/2022
  1898 000013E2 7405                <1> 	jz	short u14
  1899 000013E4 E992000000          <1> 	jmp	beeper
  1900                              <1> u14:
  1901                              <1> 	; 02/02/2022
  1902                              <1> 	;; 01/09/2014
  1903                              <1> 	;cmp	byte [CRT_MODE], 3
  1904                              <1> 	;je	short m3
  1905                              <1> 	;;
  1906                              <1> 	;call	set_mode
  1907                              <1> m3:
  1908 000013E9 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1909                              <1> 	;shl	si, 1
  1910                              <1> 	; 02/02/2022
  1911 000013EB D1E6                <1> 	shl	esi, 1
  1912 000013ED 81C6[066B0000]      <1> 	add	esi, cursor_posn
  1913 000013F3 668B16              <1> 	mov	dx, [esi]
  1914                              <1> 	;
  1915                              <1> 	; dx now has the current cursor position
  1916                              <1> 	;
  1917 000013F6 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1918 000013F8 7647                <1> 	jbe	short u8
  1919                              <1> 	;
  1920                              <1> 	; write the char to the screen
  1921                              <1> u0:	
  1922                              <1> 	; ah = attribute/color
  1923                              <1> 	; al = character
  1924                              <1> 	; bl = video page number (0 to 7)
  1925                              <1> 	; bh = 0
  1926                              <1> 	;
  1927 000013FA E8D6010000          <1> 	call	write_c_current
  1928                              <1> 	;
  1929                              <1> 	; position the cursor for next char
  1930 000013FF FEC2                <1> 	inc	dl		; next column
  1931                              <1> 	;cmp	dl, [CRT_COLS]
  1932 00001401 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1933                              <1>         ;jne	set_cpos
  1934                              <1> 	; 02/02/2022
  1935 00001404 7405                <1> 	je	short u13
  1936 00001406 E9DE000000          <1> 	jmp	set_cpos
  1937                              <1> u13:
  1938 0000140B B200                <1> 	mov	dl, 0		; column = 0
  1939                              <1> u10:				; (line feed found)
  1940 0000140D 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1941 00001410 7228                <1> 	jb 	short u6
  1942                              <1> 	;
  1943                              <1> 	; scroll required
  1944                              <1> u1:	
  1945                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1946 00001412 E8D2000000          <1> 	call	set_cpos
  1947                              <1> 	;
  1948                              <1> 	; determine value to fill with during scroll
  1949                              <1> u2:
  1950                              <1> 	; READ_AC_CURRENT		:
  1951                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1952                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1953                              <1> 	;
  1954                              <1> 	; INPUT				
  1955                              <1> 	;	(AH) = CURRENT CRT MODE
  1956                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1957                              <1> 	;	(DS) = DATA SEGMENT
  1958                              <1> 	;	(ES) = REGEN SEGMENT
  1959                              <1> 	; OUTPUT			
  1960                              <1> 	;	(AL) = CHARACTER READ
  1961                              <1> 	;	(AH) = ATTRIBUTE READ
  1962                              <1> 	;
  1963                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1964                              <1> 	;
  1965                              <1> 	; bl = video page number
  1966                              <1> 	;
  1967 00001417 E82D010000          <1> 	call	find_position	; get regen location and port address
  1968                              <1> 	; dx = status port
  1969                              <1> 	; esi = cursor location/address
  1970                              <1> p11:
  1971 0000141C FB                  <1> 	sti			; enable interrupts
  1972 0000141D 90                  <1> 	nop			; allow for small interupts window
  1973 0000141E FA                  <1> 	cli			; blocks interrupts for single loop
  1974 0000141F EC                  <1> 	in	al, dx		; get status from adapter
  1975 00001420 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1976 00001422 75F8                <1> 	jnz	short p11	; wait until it is
  1977                              <1> p12:				; now wait for either retrace high
  1978 00001424 EC                  <1> 	in	al, dx		; get status
  1979 00001425 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1980 00001427 74FB                <1> 	jz	short p12	; wait until either is active	
  1981                              <1> p13:
  1982 00001429 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1983 0000142F 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1984                              <1> 	;
  1985                              <1> 	; al = character, ah = attribute
  1986                              <1> 	;
  1987 00001432 FB                  <1> 	sti
  1988                              <1> 	; bl = video page number 	
  1989                              <1> u3:
  1990                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1991                              <1> 	;;sub	cx, cx		; upper left corner
  1992                              <1> 	;;mov	dh, 25-1 	; lower right row
  1993                              <1> 	;;;mov	dl, [CRT_COLS]
  1994                              <1> 	;mov	dl, 80		; lower right column	
  1995                              <1> 	;;dec	dl
  1996                              <1> 	;;mov	dl, 79
  1997                              <1> 
  1998                              <1> 	;;call	scroll_up	; 04/12/2013
  1999                              <1> 	;;; 11/03/2015
  2000                              <1> 	; 02/09/2014
  2001                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2002                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2003                              <1> 	; 11/03/2015
  2004                              <1> 	;sub	cx, cx
  2005                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2006                              <1> 	;
  2007                              <1> 	; 02/02/2022 (simplied scroll up)
  2008                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2009                              <1> 	;
  2010 00001433 B001                <1> 	mov	al, 1		; scroll 1 line up
  2011                              <1> 		; ah = attribute
  2012 00001435 E939010000          <1> 	jmp	scroll_up
  2013                              <1> ;u4:
  2014                              <1> 	;;int	10h		; video-call return
  2015                              <1> 				; scroll up the screen
  2016                              <1> 				; tty return
  2017                              <1> ;u5:
  2018                              <1> 	;retn			; return to the caller
  2019                              <1> 
  2020                              <1> u6:				; set-cursor-inc
  2021 0000143A FEC6                <1> 	inc	dh		; next row
  2022                              <1> 				; set cursor
  2023                              <1> ;u7:					
  2024                              <1> 	;;mov	ah, 02h
  2025                              <1> 	;;jmp	short u4 	; establish the new cursor
  2026                              <1> 	;call	set_cpos
  2027                              <1> 	;jmp 	short u5
  2028 0000143C E9A8000000          <1> 	jmp     set_cpos
  2029                              <1> 
  2030                              <1> 	; check for control characters
  2031                              <1> u8:
  2032 00001441 7434                <1> 	je	short u9
  2033 00001443 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2034 00001445 74C6                <1> 	je	short u10
  2035 00001447 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2036 00001449 7430                <1> 	je	short u11
  2037 0000144B 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2038                              <1> 	;jne	short u0
  2039 0000144D 7420                <1> 	je	short bs	; 12/12/2013
  2040                              <1> 	; 12/12/2013 (tab stop)
  2041 0000144F 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2042 00001451 75A7                <1> 	jne	short u0
  2043 00001453 88D0                <1> 	mov	al, dl
  2044 00001455 6698                <1> 	cbw
  2045 00001457 B108                <1> 	mov	cl, 8
  2046 00001459 F6F1                <1> 	div	cl
  2047 0000145B 28E1                <1> 	sub	cl, ah
  2048                              <1> ts:
  2049                              <1> 	; 02/09/2014
  2050                              <1> 	; 01/09/2014
  2051 0000145D B020                <1> 	mov	al, 20h
  2052                              <1> tsloop:
  2053                              <1> 	;push	cx
  2054                              <1> 	;push	ax
  2055                              <1> 	; 02/02/2022
  2056 0000145F 51                  <1> 	push	ecx
  2057 00001460 50                  <1> 	push	eax
  2058 00001461 30FF                <1> 	xor 	bh, bh
  2059                              <1> 	;mov	bl, [active_page]
  2060 00001463 E881FFFFFF          <1> 	call	m3
  2061                              <1> 	; 02/02/2022
  2062 00001468 58                  <1> 	pop	eax
  2063 00001469 59                  <1>  	pop	ecx
  2064                              <1> 	;pop	ax  ; ah = attribute/color
  2065                              <1> 	;pop	cx
  2066 0000146A FEC9                <1> 	dec	cl
  2067 0000146C 75F1                <1> 	jnz	short tsloop
  2068 0000146E C3                  <1> 	retn
  2069                              <1> bs:	
  2070                              <1> 	; back space found
  2071 0000146F 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2072                              <1> 	;je	short u7 	; set_cursor
  2073 00001471 7476                <1> 	jz	short set_cpos
  2074                              <1> 	;dec	dx     		; no -- just move it back
  2075                              <1> 	; 02/02/2022
  2076 00001473 FECA                <1> 	dec	dl
  2077                              <1> 	;jmp	short u7
  2078 00001475 EB72                <1> 	jmp	short set_cpos
  2079                              <1> 
  2080                              <1> 	; carriage return found
  2081                              <1> u9:
  2082 00001477 B200                <1> 	mov	dl, 0 		; move to first column
  2083                              <1> 	;jmp	short u7
  2084 00001479 EB6E                <1> 	jmp	short set_cpos
  2085                              <1> 
  2086                              <1> 	; line feed found
  2087                              <1> ;u10:
  2088                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2089                              <1> ;	jne	short u6 	; no, just set the cursor
  2090                              <1> ;       jmp     u1              ; yes, scroll the screen
  2091                              <1> 
  2092                              <1> beeper: 
  2093                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2094                              <1> 	; 18/01/2014
  2095                              <1> 	; 03/12/2013
  2096                              <1> 	; bell found
  2097                              <1> u11:
  2098 0000147B FB                  <1> 	sti
  2099 0000147C 3A1D[166B0000]      <1> 	cmp	bl, [active_page]
  2100 00001482 7551                <1> 	jne	short u12	; Do not sound the beep 
  2101                              <1> 				; if it is not written on the active page
  2102 00001484 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2103 00001488 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2104                              <1> 	;call	beep		; sound the pod bell
  2105                              <1> 	;jmp	short u5 	; tty_return
  2106                              <1> 	;retn
  2107                              <1> 	
  2108                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2109                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2110                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2111                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2112                              <1> 
  2113                              <1> beep:
  2114                              <1> 	; 07/02/2015
  2115                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2116                              <1> 	; 18/01/2014
  2117                              <1> 	; 03/12/2013
  2118                              <1> 	;
  2119                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2120                              <1> 	;
  2121                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2122                              <1> 	;
  2123                              <1> 	; ENTRY:
  2124                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2125                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2126                              <1> 	; EXIT:			:
  2127                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2128                              <1> 
  2129 0000148A 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2130 0000148B FA                  <1> 	cli			; block interrupts during update
  2131 0000148C B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2132 0000148E E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2133 00001490 EB00                <1> 	jmp	$+2		; I/O delay
  2134 00001492 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2135 00001494 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2136 00001496 EB00                <1> 	jmp	$+2		; I/O delay
  2137 00001498 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2138 0000149A E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2139 0000149C E461                <1> 	in	al, PORT_B	; get current setting of port
  2140 0000149E 88C4                <1> 	mov	ah, al		; save that setting
  2141 000014A0 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2142 000014A2 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2143                              <1> 	;popf	; 18/01/2014
  2144 000014A4 FB                  <1> 	sti
  2145                              <1> g7:				; 1/64 second per count (bl)
  2146 000014A5 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2147 000014AA E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2148 000014AF FECB                <1> 	dec	bl		; (bl) length count expired?
  2149 000014B1 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2150                              <1> 	;
  2151                              <1> 	;pushf			; save interrupt status
  2152 000014B3 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2153 000014B4 E461                <1> 	in	al, PORT_B	; get current port value
  2154                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2155 000014B6 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2156 000014B8 20C4                <1>         and	ah, al		; someone turned them off during beep
  2157 000014BA 88E0                <1> 	mov	al, ah		; recover value of port
  2158                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2159 000014BC 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2160 000014BE E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2161                              <1> 	;popf			; restore interrupt flag state
  2162 000014C0 FB                  <1> 	sti
  2163 000014C1 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2164 000014C6 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2165                              <1> 	;pushf			; save interrupt status
  2166 000014CB FA                  <1> 	cli			; block interrupts during update
  2167 000014CC E461                <1> 	in	al, PORT_B	; get current port value in case	
  2168 000014CE 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2169 000014D0 08E0                <1> 	or	al, ah		; recover value of port_b
  2170 000014D2 E661                <1> 	out	PORT_B, al	; restore speaker status
  2171 000014D4 9D                  <1> 	popf			; restore interrupt flag state
  2172                              <1> u12:	
  2173 000014D5 C3                  <1> 	retn
  2174                              <1> 
  2175                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2176                              <1> 
  2177                              <1> WAITF:
  2178                              <1> waitf:
  2179                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2180                              <1> 	; 03/12/2013
  2181                              <1> 	;
  2182                              <1> ;	push	ax		; save work register (ah)	
  2183                              <1> ;waitf1:
  2184                              <1> 				; use timer 1 output bits
  2185                              <1> ;	in	al, PORT_B	; read current counter output status
  2186                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2187                              <1> ;	cmp	al, ah		; did it just change
  2188                              <1> ;	je	short waitf1	; wait for a change in output line
  2189                              <1> ;	;
  2190                              <1> ;	mov	ah, al		; save new lflag state
  2191                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2192                              <1> ;	;
  2193                              <1> ;	pop	ax		; restore (ah)
  2194                              <1> ;	retn			; return (cx)=0
  2195                              <1> 
  2196                              <1> ; 02/02/2022
  2197                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2198                              <1> ; 17/12/2014 (dsectrm2.s)
  2199                              <1> ; WAITF
  2200                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2201                              <1> ;
  2202                              <1> ;---WAITF-----------------------------------------------------------------------
  2203                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2204                              <1> ; ENTRY:
  2205                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2206                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2207                              <1> ; EXIT:
  2208                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2209                              <1> ;	(CX) = 0	
  2210                              <1> ;-------------------------------------------------------------------------------
  2211                              <1> 
  2212                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2213                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2214                              <1> 
  2215                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2216 000014D6 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2217                              <1> 	;push	ax
  2218                              <1> 	; 16/12/2014
  2219                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2220 000014D7 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2221                              <1> ;17/12/2014	
  2222                              <1> ;WAITF1:
  2223                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2224                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2225                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2226                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2227                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2228                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2229                              <1> 	;
  2230                              <1> 	; 17/12/2014
  2231                              <1> 	;
  2232                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2233                              <1> 	;
  2234                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2235                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2236                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2237                              <1> WR_STATE_0:
  2238 000014D9 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2239 000014DB A810                <1> 	TEST	AL,010H
  2240 000014DD 74FA                <1> 	JZ	SHORT WR_STATE_0
  2241                              <1> WR_STATE_1:
  2242 000014DF E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2243 000014E1 A810                <1> 	TEST	AL,010H
  2244 000014E3 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2245 000014E5 E2F2                <1>         LOOP    WR_STATE_0
  2246                              <1> 	;
  2247                              <1> 	;pop	ax
  2248 000014E7 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2249 000014E8 C3                  <1> 	RETn				; (CX) = 0
  2250                              <1> 
  2251                              <1> set_cpos:
  2252                              <1> 	; 25/02/2022
  2253                              <1> 	; 23/02/2022
  2254                              <1> 	; 02/02/2022
  2255                              <1> 	; 27/06/2015
  2256                              <1> 	; 01/09/2014
  2257                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2258                              <1> 	;
  2259                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2260                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2261                              <1> 	;
  2262                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2263                              <1> 	;
  2264                              <1> 	; SET_CPOS
  2265                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2266                              <1> 	;	NEW X-Y VALUES PASSED
  2267                              <1> 	; INPUT
  2268                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2269                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2270                              <1> 	; OUTPUT
  2271                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2272                              <1> 	;
  2273 000014E9 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2274 000014EC D0E0                <1>         shl     al, 1   ; word offset
  2275 000014EE BE[066B0000]        <1> 	mov	esi, cursor_posn
  2276 000014F3 01C6                <1>         add     esi, eax
  2277 000014F5 668916              <1> 	mov	[esi], dx ; save the pointer
  2278 000014F8 381D[166B0000]      <1> 	cmp	[active_page], bl
  2279 000014FE 7536                <1> 	jne	short m17
  2280                              <1> 	
  2281 00001500 FA                  <1> 	cli ; 25/02/2022
  2282                              <1> 
  2283                              <1> 	;call	m18	; CURSOR SET
  2284                              <1> ;m17:			; SET_CPOS_RETURN
  2285                              <1> 	; 01/09/2014
  2286                              <1> 	;retn
  2287                              <1> 		; DX = row/column
  2288                              <1> m18:
  2289 00001501 E835000000          <1> 	call	position ; determine location in regen buffer	
  2290                              <1> 	;mov	cx, [CRT_START]
  2291                              <1> 	; 23/02/2022
  2292 00001506 0FB70D[046B0000]    <1> 	movzx	ecx, word [CRT_START]
  2293 0000150D 01C1                <1> 	add	ecx, eax
  2294                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2295                              <1> 			; to the start address (offset) for this page
  2296                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2297                              <1> 	; 23/02/2022
  2298 0000150F D1E9                <1> 	shr	ecx, 1
  2299 00001511 B40E                <1> 	mov	ah, 14	; register number for cursor
  2300                              <1> 	
  2301 00001513 E802000000          <1> 	call	m16	; output value to the 6845
  2302 00001518 FB                  <1> 	sti	; 25/02/2022
  2303 00001519 C3                  <1> 	retn
  2304                              <1> 
  2305                              <1> 	; 25/02/2022
  2306                              <1> 	; 02/02/2022
  2307                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2308                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2309                              <1> m16:
  2310                              <1> 	;cli	; 25/02/2022
  2311                              <1> 	;mov	dx, [addr_6845] ; address register
  2312 0000151A 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2313 0000151E 88E0                <1> 	mov	al, ah	; get value
  2314 00001520 EE                  <1> 	out	dx, al	; register set
  2315                              <1> 	;inc	dx	; data register
  2316                              <1> 	; 02/02/2022
  2317 00001521 FEC2                <1> 	inc	dl
  2318 00001523 EB00                <1> 	jmp	$+2	; i/o delay
  2319 00001525 88E8                <1> 	mov	al, ch	; data
  2320 00001527 EE                  <1> 	out	dx, al	
  2321                              <1> 	;dec	dx
  2322                              <1> 	; 02/02/2022	
  2323 00001528 FECA                <1> 	dec	dl
  2324 0000152A 88E0                <1> 	mov	al, ah
  2325 0000152C FEC0                <1> 	inc	al	; point to other data register
  2326 0000152E EE                  <1> 	out	dx, al	; set for second register
  2327                              <1> 	;inc	dx
  2328                              <1> 	; 02/02/2022
  2329 0000152F FEC2                <1> 	inc	dl
  2330 00001531 EB00                <1> 	jmp	$+2	; i/o delay
  2331 00001533 88C8                <1> 	mov	al, cl	; second data value
  2332 00001535 EE                  <1> 	out	dx, al
  2333                              <1> 	;sti	; 25/02/2022
  2334                              <1> m17:
  2335 00001536 C3                  <1> 	retn
  2336                              <1> 
  2337                              <1> set_ctype:
  2338                              <1> 	; 07/02/2022
  2339                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2340                              <1> 	;
  2341                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2342                              <1> 
  2343                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2344                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2345                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2346                              <1> ;          OR NO CURSOR AT ALL
  2347                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2348                              <1> 
  2349                              <1> ;------------------------------------------------
  2350                              <1> ; SET_CTYPE
  2351                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2352                              <1> ; INPUT
  2353                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2354                              <1> ; OUTPUT	
  2355                              <1> ;	NONE
  2356                              <1> ;------------------------------------------------
  2357                              <1> 
  2358 00001537 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2359                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2360                              <1> 	;call	m16	; output cx register
  2361                              <1> 	;retn
  2362                              <1> 	; 07/02/2022
  2363 00001539 EBDF                <1> 	jmp	m16
  2364                              <1> 
  2365                              <1> position:
  2366                              <1> 	; 23/02/2022
  2367                              <1> 	; 02/02/2022
  2368                              <1> 	; 27/06/2015
  2369                              <1> 	; 02/09/2014
  2370                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2371                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2372                              <1> 	;
  2373                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2374                              <1> 	;
  2375                              <1> 	; POSITION
  2376                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2377                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2378                              <1> 	; INPUT
  2379                              <1> 	;	AX = ROW, COLUMN POSITION
  2380                              <1> 	; OUTPUT
  2381                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2382                              <1> 
  2383                              <1> 		; DX = ROW, COLUMN POSITION
  2384                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2385 0000153B 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2386 0000153D B050                <1> 	mov	al, 80	; determine bytes to row	
  2387 0000153F F6E6                <1> 	mul	dh	; row value
  2388                              <1> 	;xor	dh, dh	; 0
  2389                              <1> 	;add	ax, dx	; add column value to the result
  2390                              <1> 	; 23/02/2022
  2391 00001541 00D0                <1> 	add	al, dl
  2392 00001543 80D400              <1> 	adc	ah, 0	
  2393                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2394                              <1> 	; 02/02/2022
  2395 00001546 D1E0                <1> 	shl	eax, 1
  2396                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2397 00001548 C3                  <1> 	retn
  2398                              <1> 
  2399                              <1> find_position:
  2400                              <1> 	; 02/02/2022
  2401                              <1> 	; 27/06/2015
  2402                              <1> 	; 07/09/2014
  2403                              <1> 	; 02/09/2014
  2404                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2405                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2406 00001549 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2407 0000154C 89CE                <1> 	mov	esi, ecx
  2408                              <1> 	;shl	si, 1
  2409                              <1> 	; 02/02/2022
  2410 0000154E D1E6                <1> 	shl	esi, 1
  2411 00001550 668B96[066B0000]    <1> 	mov	dx, [esi+cursor_posn]
  2412 00001557 7409                <1> 	jz	short p21
  2413                              <1> 	;xor	si, si
  2414                              <1> 	; 02/02/2022
  2415 00001559 31F6                <1> 	xor	esi, esi
  2416                              <1> p20:
  2417                              <1> 	;add	si, [CRT_LEN]
  2418 0000155B 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2419 00001560 E2F9                <1> 	loop	p20
  2420                              <1> p21:
  2421 00001562 6621D2              <1> 	and	dx, dx
  2422 00001565 7407                <1> 	jz	short p22
  2423 00001567 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2424 0000156C 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2425                              <1> p22:	
  2426                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2427                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2428                              <1> 	;add	dx, 6	; point at status port
  2429 0000156E 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2430                              <1> 	; cx = 0
  2431 00001572 C3                  <1> 	retn
  2432                              <1> 
  2433                              <1> scroll_up:
  2434                              <1> 	; 02/02/2022 (simplified scroll up)
  2435                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2436                              <1> 	; 16/01/2016
  2437                              <1> 	; 07/09/2014
  2438                              <1> 	; 02/09/2014
  2439                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2440                              <1> 	; 04/04/2014
  2441                              <1> 	; 04/12/2013
  2442                              <1> 	;
  2443                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2444                              <1> 	;
  2445                              <1> 	; SCROLL UP
  2446                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2447                              <1> 	;	ON THE SCREEN
  2448                              <1> 	; INPUT
  2449                              <1> 	;	(AH) = CURRENT CRT MODE
  2450                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2451                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2452                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2453                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2454                              <1> 	;	(DS) = DATA SEGMENT
  2455                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2456                              <1> 	; OUTPUT
  2457                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2458                              <1> 	;
  2459                              <1> 	;	bh = 0  (02/09/2014)
  2460                              <1> 	;
  2461                              <1> 	; ((ah = 3))
  2462                              <1> 	; cl = left upper column
  2463                              <1> 	; ch = left upper row
  2464                              <1> 	; dl = right lower column
  2465                              <1> 	; dh = right lower row
  2466                              <1> 	;
  2467                              <1> 	; al = line count 
  2468                              <1> 	; ah = attribute to be used on blanked line
  2469                              <1> 	; bl = video page number (0 to 7)
  2470                              <1> 	; 
  2471                              <1> 
  2472                              <1> 	; 02/02/2022 'scroll_up' code
  2473                              <1> 	; ------------------------------------------------------
  2474                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2475                              <1> 
  2476                              <1> 	; INPUT:
  2477                              <1> 	;		
  2478                              <1> 	; al = line count 
  2479                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2480                              <1> 	; ah = attribute to be used on blanked line
  2481                              <1> 	; bl = video page number (0 to 7)
  2482                              <1> 
  2483                              <1> 	;cli
  2484 00001573 31C9                <1> 	xor	ecx, ecx
  2485 00001575 88C1                <1> 	mov	cl, al ; line count (cl)
  2486 00001577 BE00800B00          <1> 	mov	esi, 0B8000h
  2487 0000157C 3A1D[166B0000]      <1> 	cmp	bl, [active_page]
  2488 00001582 7411                <1> 	je	short n1
  2489 00001584 20DB                <1> 	and	bl, bl
  2490 00001586 7422                <1> 	jz	short n3
  2491 00001588 88DD                <1> 	mov	ch, bl ; video page number
  2492                              <1> n0:
  2493 0000158A 6681C6A00F          <1> 	add	si, 25*80*2
  2494 0000158F FECD                <1> 	dec	ch
  2495 00001591 75F7                <1> 	jnz	short n0
  2496 00001593 EB15                <1> 	jmp	short n3
  2497                              <1> n1:
  2498 00001595 660335[046B0000]    <1> 	add	si, [CRT_START]
  2499                              <1> 	;
  2500 0000159C 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2501                              <1> n2:			 ; wait_display_enable
  2502 000015A0 EC                  <1> 	in	al, dx	 ; get port
  2503 000015A1 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2504 000015A3 74FB                <1> 	jz	short n2 ; wait_display_enable
  2505 000015A5 B025                <1> 	mov	al, 25h
  2506 000015A7 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2507 000015A9 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2508                              <1> n3:
  2509                              <1> 	; cl = line count
  2510                              <1> 	; ah = attribute/color
  2511 000015AA 89F7                <1> 	mov	edi, esi
  2512 000015AC 20C9                <1> 	and	cl, cl
  2513 000015AE 741F                <1> 	jz	short n6
  2514 000015B0 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2515 000015B5 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2516 000015B9 F366A5              <1> 	rep	movsw
  2517 000015BC B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2518                              <1> n4:
  2519                              <1> 	; ah = character attribute/cocor
  2520 000015BE B020                <1> 	mov	al, 20h ; fill with blanks
  2521 000015C0 F366AB              <1> 	rep	stosw
  2522                              <1> 
  2523 000015C3 3A1D[166B0000]      <1> 	cmp	bl, [active_page]
  2524 000015C9 7503                <1> 	jne	short n5
  2525                              <1> 
  2526                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2527 000015CB B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2528                              <1> 	;mov	dx, 03D8h ; always set color card port
  2529 000015CD EE                  <1> 	out	dx, al
  2530                              <1> n5:
  2531 000015CE C3                  <1> 	retn
  2532                              <1> n6:
  2533                              <1> 	; clear video page
  2534 000015CF 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2535 000015D3 EBE9                <1> 	jmp	short n4
  2536                              <1> 
  2537                              <1> 	; 23/02/2022
  2538                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2539                              <1> 	; ------------------------------------------------------
  2540                              <1> 
  2541                              <1> 	; Test	Line Count
  2542                              <1> 	or	al, al
  2543                              <1> 	jz	short al_set
  2544                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2545                              <1> 	sub	bh, ch
  2546                              <1> 	inc	bh	; adjust difference by 1
  2547                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2548                              <1> 	jne	short al_set ; if not the we're all set
  2549                              <1> 	xor	al, al	; otherwise set al to zero
  2550                              <1> al_set:
  2551                              <1> 	xor	bh, bh	; 0
  2552                              <1> 	;push	ax
  2553                              <1> 	push	eax ; 23/02/2022
  2554                              <1> 	;mov 	esi, [crt_base]
  2555                              <1>         mov     esi, 0B8000h  
  2556                              <1>         cmp     bl, [active_page]
  2557                              <1> 	jne	short n0
  2558                              <1> 	;
  2559                              <1>         mov     ax, [CRT_START]
  2560                              <1>         add     si, ax
  2561                              <1>         jmp     short n1
  2562                              <1> n0:
  2563                              <1>         and     bl, bl
  2564                              <1> 	jz	short n1
  2565                              <1> 	mov	al, bl
  2566                              <1> n0x:
  2567                              <1>         ;add    si, [CRT_LEN]
  2568                              <1>         ;add    esi, 80*25*2 
  2569                              <1>         add     si, 80*25*2
  2570                              <1>         dec	al
  2571                              <1> 	jnz	short n0x
  2572                              <1> n1:	
  2573                              <1>         ; Scroll position
  2574                              <1> 	;push	dx ; 23/02/2022
  2575                              <1> 	mov	dx, cx	; now, upper left position in DX
  2576                              <1> 	call	position
  2577                              <1> 	add	esi, eax
  2578                              <1> 	mov	edi, esi
  2579                              <1> 	;pop	dx	; lower right position in DX
  2580                              <1> 	sub	dx, cx
  2581                              <1> 	inc	dh	; dh = #rows 
  2582                              <1> 	inc	dl	; dl = #cols in block
  2583                              <1> 	;pop	ax	; al = line count, ah = attribute
  2584                              <1> 	pop	eax ; 23/02/2022
  2585                              <1> 	xor	ecx, ecx
  2586                              <1> 	mov	cx, ax
  2587                              <1> 	;mov	ah, [CRT_COLS]
  2588                              <1> 	mov	ah, 80
  2589                              <1> 	mul	ah	; determine offset to from address
  2590                              <1> 	add	ax, ax  ; *2 for attribute byte
  2591                              <1> 	;
  2592                              <1> 	;push	ax	; offset 
  2593                              <1> 	;push	dx
  2594                              <1> 	; 23/02/2022
  2595                              <1> 	push	eax
  2596                              <1> 	push	edx
  2597                              <1> 	;
  2598                              <1> 	; 04/04/2014
  2599                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2600                              <1> n8:                      ; wait_display_enable
  2601                              <1>         in      al, dx   ; get port
  2602                              <1> 	test	al, RVRT ; wait for vertical retrace
  2603                              <1> 	jz	short n8 ; wait_display_enable
  2604                              <1> 	mov	al, 25h
  2605                              <1> 	mov	dl, 0D8h ; address control port
  2606                              <1> 	out	dx, al	; turn off video during vertical retrace
  2607                              <1> 	;pop	dx	; #rows, #cols
  2608                              <1>        	;pop	ax	; offset
  2609                              <1> 	; 23/02/2022
  2610                              <1> 	pop	edx
  2611                              <1> 	pop	eax
  2612                              <1> 	xchg	ax, cx	; 
  2613                              <1> 	; ecx = offset, al = line count, ah = attribute
  2614                              <1> ;n9:
  2615                              <1> 	or	al, al
  2616                              <1>         jz      short n3 
  2617                              <1>         add     esi, ecx ; from address for scroll
  2618                              <1> 	mov	bh, dh  ; #rows in block
  2619                              <1> 	sub	bh, al	; #rows to be moved
  2620                              <1> n2:
  2621                              <1> 	; Move rows
  2622                              <1> 	mov	cl, dl	; get # of cols to move
  2623                              <1> 	push	esi
  2624                              <1> 	push	edi	; save start address
  2625                              <1> n10:
  2626                              <1> 	movsw		; move that line on screen
  2627                              <1> 	dec	cl
  2628                              <1>         jnz     short n10
  2629                              <1> 	pop	edi
  2630                              <1> 	pop	esi	; recover addresses
  2631                              <1>         ;mov    cl, [CRT_COLS] 
  2632                              <1> 	;add	cl, cl
  2633                              <1>         ;mov    ecx, 80*2
  2634                              <1>         mov     cx, 80*2
  2635                              <1>         add     esi, ecx  ; next line
  2636                              <1>         add     edi, ecx
  2637                              <1> 	dec	bh	 ; count of lines to move
  2638                              <1> 	jnz	short n2 ; row loop
  2639                              <1> 	; bh = 0
  2640                              <1> 	mov	dh, al	 ; #rows	
  2641                              <1> n3:
  2642                              <1> 	; attribute in ah
  2643                              <1> 	mov	al, ' '	 ; fill with blanks
  2644                              <1> n3x:
  2645                              <1> 	; Clear rows
  2646                              <1>                 ; dh =  #rows
  2647                              <1>         mov	cl, dl	; get # of cols to clear
  2648                              <1>         push    edi     ; save address
  2649                              <1> n11:
  2650                              <1>         stosw           ; store fill character
  2651                              <1> 	dec	cl
  2652                              <1>         jnz     short n11
  2653                              <1>         pop     edi     ; recover address
  2654                              <1> 	;mov	cl, [CRT_COLS]
  2655                              <1> 	;add	cl, cl
  2656                              <1>         ;mov    ecx, 80*2
  2657                              <1>         mov	cl, 80*2
  2658                              <1>         add     edi, ecx
  2659                              <1> 	dec	dh
  2660                              <1> 	jnz	short n3x ; 16/01/2016
  2661                              <1> 	;
  2662                              <1> 	cmp	bl, [active_page]
  2663                              <1> 	jne	short n6
  2664                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2665                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2666                              <1> 	mov	dx, 03D8h ; always set color card port
  2667                              <1> 	out	dx, al
  2668                              <1> n6:
  2669                              <1> 	retn
  2670                              <1> 
  2671                              <1> %endif
  2672                              <1> 
  2673                              <1> write_c_current:
  2674                              <1> 	; 02/02/2022
  2675                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2676                              <1> 	; 18/01/2014
  2677                              <1> 	; 04/12/2013
  2678                              <1> 	;
  2679                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2680                              <1> 	;
  2681                              <1> 	; WRITE_C_CURRENT
  2682                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2683                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2684                              <1> 	; INPUT	
  2685                              <1> 	;	(AH) = CURRENT CRT MODE
  2686                              <1> 	;	(BH) = DISPLAY PAGE
  2687                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2688                              <1> 	;	(AL) = CHAR TO WRITE
  2689                              <1> 	;	(DS) = DATA SEGMENT
  2690                              <1> 	;	(ES) = REGEN SEGMENT
  2691                              <1> 	; OUTPUT
  2692                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2693                              <1> 
  2694 000015D5 FA                  <1> 	cli		
  2695                              <1> 	; bl = video page
  2696                              <1> 	; al = character
  2697                              <1> 	; ah = color/attribute
  2698                              <1> 	;push	dx
  2699                              <1> 	;push	ax	; save character & attribute/color
  2700                              <1> 	; 02/02/2022
  2701 000015D6 52                  <1> 	push	edx
  2702 000015D7 50                  <1> 	push	eax
  2703 000015D8 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2704                              <1> 	; esi = regen location
  2705                              <1> 	; dx = status port
  2706                              <1> 	;
  2707                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2708                              <1> 	;
  2709                              <1> p41:			; wait for horizontal retrace is low or vertical
  2710 000015DD FB                  <1> 	sti		; enable interrupts first
  2711 000015DE 3A1D[166B0000]      <1>         cmp     bl, [active_page]
  2712 000015E4 7510                <1> 	jne	short p44 
  2713 000015E6 FA                  <1> 	cli 		; block interrupts for single loop
  2714 000015E7 EC                  <1> 	in	al, dx	; get status from the adapter
  2715 000015E8 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2716 000015EA 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2717 000015EC A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2718 000015EE 75ED                <1> 	jnz	short p41 ; wait until it is
  2719                              <1> p42:			; wait for either retrace high
  2720 000015F0 EC                  <1> 	in	al, dx	; get status again
  2721 000015F1 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2722 000015F3 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2723                              <1> p43:	
  2724 000015F5 FB                  <1> 	sti
  2725                              <1> p44:
  2726                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2727                              <1> 	; 02/02/2022
  2728 000015F6 58                  <1> 	pop	eax
  2729 000015F7 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2730                              <1> 			; Retro UNIX 386 v1 feature only!
  2731 000015FD 668906              <1> 	mov	[esi], ax
  2732                              <1> 	;pop	dx
  2733                              <1> 	; 02/02/2022
  2734 00001600 5A                  <1> 	pop	edx
  2735 00001601 C3                  <1> 	retn
  2736                              <1> 
  2737                              <1> %if 0	; 02/02/2022
  2738                              <1> 
  2739                              <1> set_mode:
  2740                              <1> 	; 02/02/2022
  2741                              <1> 	; 16/01/2016
  2742                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2743                              <1> 	;
  2744                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2745                              <1> 
  2746                              <1> ;------------------------------------------------------
  2747                              <1> ; SET MODE					      :
  2748                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2749                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2750                              <1> ; INPUT						      :
  2751                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2752                              <1> ; OUTPUT					      :
  2753                              <1> ;	NONE					      :
  2754                              <1> ;------------------------------------------------------
  2755                              <1> 
  2756                              <1> 	push	edi ; 16/01/2016
  2757                              <1> 	push	ebx
  2758                              <1> 	push	edx
  2759                              <1> 	push	ecx ; 16/01/2016
  2760                              <1>         push    eax
  2761                              <1> 
  2762                              <1> 	;mov	dx, 03D4h 	; address or color card
  2763                              <1> 	mov	al, 3
  2764                              <1> ;M8:
  2765                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2766                              <1> 	mov	al, 29h
  2767                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2768                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2769                              <1> 	;push	dx  		; save port value
  2770                              <1> 	;add	dx, 4		; point to control register
  2771                              <1> 	mov	dx, 3D8h
  2772                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2773                              <1> 	;pop	dx
  2774                              <1> ;M9:
  2775                              <1> 	mov	ebx, video_params ; initialization table
  2776                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2777                              <1> 	;xchg 	ah, al
  2778                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2779                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2780                              <1> 	
  2781                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2782                              <1> 	; 02/02/2022
  2783                              <1> 	; dx = 3D8h
  2784                              <1> 	xor	ecx, ecx
  2785                              <1> 	mov	cl, 16
  2786                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2787                              <1> M10:			;  initialization loop
  2788                              <1> 	mov	al, ah 	; get 6845 register number
  2789                              <1> 	out	dx, al
  2790                              <1> 	;inc	dx      ; point to data port
  2791                              <1> 	; 02/02/2022
  2792                              <1> 	inc	dl ; 3D9h
  2793                              <1> 	inc	ah	; next register value
  2794                              <1> 	mov	al, [ebx] ; get table value
  2795                              <1> 	out	dx, al	; out to chip
  2796                              <1> 	inc	ebx	; next in table
  2797                              <1> 	;dec	dx	; back to pointer register
  2798                              <1> 	; 02/02/2022
  2799                              <1> 	dec	dl ; 3D8h
  2800                              <1> 	loop	M10	; do the whole table
  2801                              <1> 	
  2802                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2803                              <1> 	;xor	ax, ax  
  2804                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2805                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2806                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2807                              <1> 	; black background, light gray characeter color, space character
  2808                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2809                              <1> ;M13:			  ; clear buffer
  2810                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2811                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2812                              <1> 
  2813                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2814                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2815                              <1> 			 ; prepare to output to video enable port
  2816                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2817                              <1> 	; 02/02/2022
  2818                              <1> 	;mov	dx, 3D8h
  2819                              <1> 	; 
  2820                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2821                              <1> 	mov	al, 29h
  2822                              <1> 	out	dx, al	 ; set video enable port
  2823                              <1> 
  2824                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2825                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2826                              <1> 	;
  2827                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2828                              <1> 	;
  2829                              <1> ;-----	SET CURSOR POSITIONS
  2830                              <1> 	;push	edi
  2831                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2832                              <1> 	mov	edi, cursor_posn
  2833                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2834                              <1> 	xor	eax, eax
  2835                              <1> 	rep 	stosd	; fill with zeroes
  2836                              <1> 	;pop	edi
  2837                              <1> 
  2838                              <1> ;-----	SET UP OVERSCAN REGISTER
  2839                              <1> 	inc	dx	; set overscan port to a default
  2840                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2841                              <1> ;M14:
  2842                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2843                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2844                              <1> 
  2845                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2846                              <1> 	;
  2847                              <1> 	pop	eax
  2848                              <1> 	pop	ecx ; 16/01/2016
  2849                              <1> 	pop	edx
  2850                              <1> 	pop	ebx
  2851                              <1> 	pop	edi ; 16/01/2016
  2852                              <1> 	retn
  2853                              <1> 
  2854                              <1> %endif
  2855                              <1> 	
  2856                              <1> tty_sw:
  2857                              <1> 	; 02/02/2022
  2858                              <1> 	; 30/06/2015
  2859                              <1> 	; 27/06/2015 
  2860                              <1> 	; 07/09/2014
  2861                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2862                              <1> 	;
  2863                              <1> 	; (Modified registers : EAX)
  2864                              <1> 	;
  2865                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2866                              <1> 	;
  2867                              <1> ;act_disp_page:
  2868                              <1> 	; 30/06/2015
  2869                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2870                              <1> 	; 10/12/2013
  2871                              <1> 	; 04/12/2013
  2872                              <1> 	;
  2873                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2874                              <1> 	;
  2875                              <1> 	; ACT_DISP_PAGE
  2876                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2877                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2878                              <1> 	; INPUT
  2879                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2880                              <1> 	; OUTPUT
  2881                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2882                              <1> 
  2883                              <1> 	;cli
  2884                              <1> 
  2885 00001602 53                  <1> 	push	ebx
  2886                              <1> 	;push	cx
  2887                              <1> 	;push	dx
  2888                              <1> 	; 02/02/2022
  2889 00001603 51                  <1> 	push	ecx
  2890 00001604 52                  <1> 	push	edx
  2891                              <1> 	;
  2892 00001605 A2[166B0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2893                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2894                              <1> 	;mov	cx, 25*80*2
  2895                              <1> 	; 02/02/2022
  2896 0000160A B9A00F0000          <1> 	mov	ecx, 25*80*2
  2897                              <1> 	; 27/06/2015
  2898 0000160F 0FB6D8              <1> 	movzx	ebx, al
  2899                              <1> 	; 02/02/2022
  2900 00001612 89D8                <1> 	mov	eax, ebx
  2901                              <1> 	;
  2902                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2903                              <1> 	;mul 	cx	; display page times regen length
  2904                              <1> 	; 02/02/2022
  2905 00001614 F7E1                <1> 	mul	ecx	
  2906                              <1> 	; 10/12/2013
  2907 00001616 66A3[046B0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2908                              <1> 	;mov	cx, ax	; start address to cx
  2909                              <1> 	; 02/02/2022
  2910 0000161C 89C1                <1> 	mov	ecx, eax
  2911                              <1> 	;sar	cx, 1
  2912                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2913                              <1> 	; 02/02/2022
  2914 0000161E D1E9                <1> 	shr	ecx, 1
  2915 00001620 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2916 00001622 E8F3FEFFFF          <1> 	call	m16
  2917                              <1> 	;sal	bx, 1
  2918                              <1> 	; 01/09/2014
  2919 00001627 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2920 00001629 81C3[066B0000]      <1> 	add	ebx, cursor_posn
  2921 0000162F 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2922 00001632 E8CAFEFFFF          <1> 	call	m18
  2923                              <1> 	;
  2924                              <1> 	;pop	dx
  2925                              <1> 	;pop	cx
  2926                              <1> 	; 02/02/2022
  2927 00001637 5A                  <1> 	pop	edx
  2928 00001638 59                  <1> 	pop	ecx
  2929 00001639 5B                  <1> 	pop	ebx
  2930                              <1> 	;
  2931                              <1> 	;sti
  2932                              <1> 	;
  2933 0000163A C3                  <1> 	retn
  2934                              <1> 
  2935                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2936                              <1> 
  2937                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1830                                  
  1831                                  setup_rtc_int:
  1832                                  ; source: http://wiki.osdev.org/RTC
  1833 0000163B FA                      	cli		; disable interrupts
  1834                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1835                                  	; in order to change this ...
  1836                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1837                                  	; (rate must be above 2 and not over 15)
  1838                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1839 0000163C B08A                    	mov	al, 8Ah 
  1840 0000163E E670                    	out	70h, al ; set index to register A, disable NMI
  1841 00001640 90                      	nop
  1842 00001641 E471                    	in	al, 71h ; get initial value of register A
  1843 00001643 88C4                    	mov 	ah, al
  1844 00001645 80E4F0                  	and	ah, 0F0h
  1845 00001648 B08A                    	mov	al, 8Ah 
  1846 0000164A E670                    	out	70h, al ; reset index to register A
  1847 0000164C 88E0                    	mov	al, ah
  1848 0000164E 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1849 00001650 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1850                                  	; enable RTC interrupt
  1851 00001652 B08B                    	mov	al, 8Bh ;
  1852 00001654 E670                    	out	70h, al ; select register B and disable NMI
  1853 00001656 90                      	nop
  1854 00001657 E471                    	in	al, 71h ; read the current value of register B
  1855 00001659 88C4                    	mov	ah, al  ;
  1856 0000165B B08B                    	mov 	al, 8Bh ;
  1857 0000165D E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1858 0000165F 88E0                    	mov	al, ah  ;
  1859 00001661 0C40                    	or	al, 40h ;
  1860 00001663 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1861 00001665 FB                      	sti
  1862 00001666 C3                      	retn
  1863                                  
  1864                                  ; Write memory information
  1865                                  ; Temporary Code
  1866                                  ; 06/11/2014
  1867                                  ; 14/08/2015 
  1868                                  memory_info:	
  1869 00001667 A1[EC6A0000]            	mov	eax, [memory_size] ; in pages
  1870 0000166C 50                      	push	eax
  1871 0000166D C1E00C                  	shl	eax, 12		   ; in bytes
  1872 00001670 BB0A000000              	mov	ebx, 10
  1873 00001675 89D9                    	mov	ecx, ebx	   ; 10
  1874 00001677 BE[4F670000]            	mov	esi, mem_total_b_str	
  1875 0000167C E8B2000000              	call	bintdstr
  1876 00001681 58                      	pop	eax
  1877 00001682 B107                    	mov	cl, 7
  1878 00001684 BE[73670000]            	mov	esi, mem_total_p_str
  1879 00001689 E8A5000000              	call	bintdstr	
  1880                                  	; 14/08/2015
  1881 0000168E E8BD000000              	call	calc_free_mem
  1882                                  	; edx = calculated free pages
  1883                                  	; ecx = 0
  1884 00001693 A1[F06A0000]            	mov 	eax, [free_pages]
  1885 00001698 39D0                    	cmp	eax, edx ; calculated free mem value 
  1886                                  		; and initial free mem value are same or not?
  1887 0000169A 751D                    	jne 	short pmim ; print mem info with '?' if not
  1888 0000169C 52                      	push 	edx ; free memory in pages	
  1889                                  	;mov 	eax, edx
  1890 0000169D C1E00C                  	shl	eax, 12 ; convert page count
  1891                                  			; to byte count
  1892 000016A0 B10A                    	mov	cl, 10
  1893 000016A2 BE[93670000]            	mov	esi, free_mem_b_str
  1894 000016A7 E887000000              	call	bintdstr
  1895 000016AC 58                      	pop	eax
  1896 000016AD B107                    	mov	cl, 7
  1897 000016AF BE[B7670000]            	mov	esi, free_mem_p_str
  1898 000016B4 E87A000000              	call	bintdstr
  1899                                  pmim:
  1900 000016B9 BE[3D670000]            	mov	esi, msg_memory_info
  1901                                  pmim_nb:	
  1902 000016BE AC                      	lodsb
  1903 000016BF 08C0                    	or	al, al
  1904 000016C1 740D                    	jz	short pmim_ok
  1905 000016C3 56                      	push	esi
  1906 000016C4 31DB                    	xor	ebx, ebx ; 0
  1907                                  			; Video page 0 (bl=0)
  1908 000016C6 B407                    	mov	ah, 07h ; Black background, 
  1909                                  			; light gray forecolor
  1910 000016C8 E812FDFFFF              	call	write_tty
  1911 000016CD 5E                      	pop	esi
  1912 000016CE EBEE                    	jmp	short pmim_nb
  1913                                  pmim_ok:
  1914 000016D0 C3                      	retn
  1915                                  
  1916                                  ; Convert binary number to hexadecimal string
  1917                                  ; 10/05/2015  
  1918                                  ; dsectpm.s (28/02/2015)
  1919                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1920                                  ; 01/12/2014
  1921                                  ; 25/11/2014
  1922                                  ;
  1923                                  bytetohex:
  1924                                  	; INPUT ->
  1925                                  	; 	AL = byte (binary number)
  1926                                  	; OUTPUT ->
  1927                                  	;	AX = hexadecimal string
  1928                                  	;
  1929 000016D1 53                      	push	ebx
  1930 000016D2 31DB                    	xor	ebx, ebx
  1931 000016D4 88C3                    	mov	bl, al
  1932 000016D6 C0EB04                  	shr	bl, 4
  1933 000016D9 8A9B[23170000]          	mov	bl, [ebx+hexchrs] 	 	
  1934 000016DF 86D8                    	xchg	bl, al
  1935 000016E1 80E30F                  	and	bl, 0Fh
  1936 000016E4 8AA3[23170000]          	mov	ah, [ebx+hexchrs] 
  1937 000016EA 5B                      	pop	ebx	
  1938 000016EB C3                      	retn
  1939                                  
  1940                                  wordtohex:
  1941                                  	; INPUT ->
  1942                                  	; 	AX = word (binary number)
  1943                                  	; OUTPUT ->
  1944                                  	;	EAX = hexadecimal string
  1945                                  	;
  1946 000016EC 53                      	push	ebx
  1947 000016ED 31DB                    	xor	ebx, ebx
  1948 000016EF 86E0                    	xchg	ah, al
  1949 000016F1 6650                    	push	ax
  1950 000016F3 88E3                    	mov	bl, ah
  1951 000016F5 C0EB04                  	shr	bl, 4
  1952 000016F8 8A83[23170000]          	mov	al, [ebx+hexchrs] 	 	
  1953 000016FE 88E3                    	mov	bl, ah
  1954 00001700 80E30F                  	and	bl, 0Fh
  1955 00001703 8AA3[23170000]          	mov	ah, [ebx+hexchrs]
  1956 00001709 C1E010                  	shl	eax, 16
  1957 0000170C 6658                    	pop	ax
  1958 0000170E 5B                      	pop	ebx
  1959 0000170F EBC0                    	jmp	short bytetohex
  1960                                  	;mov	bl, al
  1961                                  	;shr	bl, 4
  1962                                  	;mov	bl, [ebx+hexchrs] 	 	
  1963                                  	;xchg	bl, al	 	
  1964                                  	;and	bl, 0Fh
  1965                                  	;mov	ah, [ebx+hexchrs] 
  1966                                  	;pop	ebx	
  1967                                  	;retn
  1968                                  
  1969                                  dwordtohex:
  1970                                  	; INPUT ->
  1971                                  	; 	EAX = dword (binary number)
  1972                                  	; OUTPUT ->
  1973                                  	;	EDX:EAX = hexadecimal string
  1974                                  	;
  1975 00001711 50                      	push	eax
  1976 00001712 C1E810                  	shr	eax, 16
  1977 00001715 E8D2FFFFFF              	call	wordtohex
  1978 0000171A 89C2                    	mov	edx, eax
  1979 0000171C 58                      	pop	eax
  1980 0000171D E8CAFFFFFF              	call	wordtohex
  1981 00001722 C3                      	retn
  1982                                  
  1983                                  ; 10/05/2015
  1984                                  hex_digits:
  1985                                  hexchrs:
  1986 00001723 303132333435363738-     	db '0123456789ABCDEF'
  1986 0000172C 39414243444546     
  1987                                  
  1988                                  ; Convert binary number to decimal/numeric string
  1989                                  ; 06/11/2014
  1990                                  ; Temporary Code
  1991                                  ;
  1992                                  
  1993                                  bintdstr:
  1994                                  	; EAX = binary number
  1995                                  	; ESI = decimal/numeric string address
  1996                                  	; EBX = divisor (10)
  1997                                  	; ECX = string length (<=10)
  1998 00001733 01CE                    	add	esi, ecx
  1999                                  btdstr0:
  2000 00001735 4E                      	dec	esi
  2001 00001736 31D2                    	xor	edx, edx
  2002 00001738 F7F3                    	div	ebx
  2003 0000173A 80C230                  	add	dl, 30h
  2004 0000173D 8816                    	mov	[esi], dl
  2005 0000173F FEC9                    	dec	cl
  2006 00001741 740C                    	jz	btdstr2
  2007 00001743 09C0                    	or	eax, eax
  2008 00001745 75EE                    	jnz	short btdstr0
  2009                                  btdstr1:
  2010 00001747 4E                      	dec	esi
  2011 00001748 C60620                          mov     byte [esi], 20h ; blank space
  2012 0000174B FEC9                    	dec	cl
  2013 0000174D 75F8                    	jnz	short btdstr1
  2014                                  btdstr2:
  2015 0000174F C3                      	retn
  2016                                  
  2017                                  ; Calculate free memory pages on M.A.T.
  2018                                  ; 06/11/2014
  2019                                  ; Temporary Code
  2020                                  ;
  2021                                  
  2022                                  calc_free_mem:
  2023 00001750 31D2                    	xor	edx, edx
  2024                                  	;xor	ecx, ecx
  2025 00001752 668B0D[006B0000]        	mov	cx, [mat_size] ; in pages
  2026 00001759 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2027 0000175C BE00001000              	mov	esi, MEM_ALLOC_TBL
  2028                                  cfm0:
  2029 00001761 AD                      	lodsd
  2030 00001762 51                      	push	ecx
  2031 00001763 B920000000              	mov	ecx, 32
  2032                                  cfm1:
  2033 00001768 D1E8                    	shr	eax, 1
  2034 0000176A 7301                    	jnc	short cfm2
  2035 0000176C 42                      	inc	edx
  2036                                  cfm2:
  2037 0000176D E2F9                    	loop	cfm1
  2038 0000176F 59                      	pop	ecx
  2039 00001770 E2EF                    	loop	cfm0
  2040 00001772 C3                      	retn
  2041                                  
  2042                                  %include 'diskio.inc'  ; 07/03/2015
  2043                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  2044                              <1> ; Last Modification: 24/12/2021
  2045                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2046                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2047                              <1> 
  2048                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2049                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2050                              <1> 
  2051                              <1> ; 06/02/2015
  2052                              <1> diskette_io:
  2053 00001773 9C                  <1> 	pushfd
  2054 00001774 0E                  <1> 	push 	cs
  2055 00001775 E809000000          <1> 	call 	DISKETTE_IO_1
  2056 0000177A C3                  <1> 	retn
  2057                              <1> 	
  2058                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2059                              <1> ;//////////////////////////////////////////////////////
  2060                              <1> 
  2061                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2062                              <1> 
  2063                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2064                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2065                              <1> ; 20/02/2015
  2066                              <1> ; 06/02/2015 (Retro UNIX 386 v1, unix386.s)
  2067                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2068                              <1> ;
  2069                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2070                              <1> ;
  2071                              <1> ; ADISK.EQU
  2072                              <1> 
  2073                              <1> ;----- Wait control constants 
  2074                              <1> 
  2075                              <1> ;amount of time to wait while RESET is active.
  2076                              <1> 
  2077                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2078                              <1> 					;at 250 KBS xfer rate.
  2079                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2080                              <1> 
  2081                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2082                              <1> 					;status register to become valid
  2083                              <1> 					;before re-reading.
  2084                              <1> 
  2085                              <1> ;After sending a byte to NEC, status register may remain
  2086                              <1> ;incorrectly set for 24 us.
  2087                              <1> 
  2088                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2089                              <1> 					;RQM low.
  2090                              <1> 
  2091                              <1> ; COMMON.MAC
  2092                              <1> ;
  2093                              <1> ;	Timing macros
  2094                              <1> ;
  2095                              <1> 
  2096                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2097                              <1> 		jmp short $+2
  2098                              <1> %endmacro		
  2099                              <1> 
  2100                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2101                              <1> 		jmp short $+2
  2102                              <1> 		jmp short $+2
  2103                              <1> %endmacro
  2104                              <1> 
  2105                              <1> %macro		NEWIODELAY 0
  2106                              <1> 		out	0EBh,al
  2107                              <1> %endmacro 
  2108                              <1> 
  2109                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2110                              <1> ;;; WAIT_FOR_MEM
  2111                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2112                              <1> ;WAIT_FDU_INT_HI	equ	1
  2113                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2114                              <1> ;;; WAIT_FOR_PORT
  2115                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2116                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2117                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2118                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2119                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2120                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2121                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2122                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2123                              <1> ;;; WAIT_REFRESH
  2124                              <1> ;amount of time to wait for head settle, per unit in parameter
  2125                              <1> ;table = 1 ms.
  2126                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2127                              <1> 
  2128                              <1> 
  2129                              <1> ; //////////////// DISKETTE I/O ////////////////
  2130                              <1> 
  2131                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2132                              <1> 
  2133                              <1> ;----------------------------------------
  2134                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2135                              <1> ;----------------------------------------
  2136                              <1> 
  2137                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2138                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2139                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2140                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2141                              <1> 
  2142                              <1> ;----------------------------------------
  2143                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2144                              <1> ;-------------------------------------------------------------------------------
  2145                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2146                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2147                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2148                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2149                              <1> 
  2150                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2151                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2152                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2153                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2154                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2155                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2156                              <1> 
  2157                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2158                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2159                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2160                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2161                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2162                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2163                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2164                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2165                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2166                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2167                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2168                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2169                              <1> 
  2170                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2171                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2172                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2173                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2174                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2175                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2176                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2177                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2178                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2179                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2180                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2181                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2182                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2183                              <1> 
  2184                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2185                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2186                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2187                              <1> 
  2188                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2189                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2190                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2191                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2192                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2193                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2194                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2195                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2196                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2197                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2198                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2199                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2200                              <1> 
  2201                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2202                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2203                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2204                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2205                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2206                              <1> 
  2207                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2208                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2209                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2210                              <1> INTA01		EQU	021H		; 8259 PORT
  2211                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2212                              <1> INTB01		EQU	0A1H		;
  2213                              <1> 
  2214                              <1> ;-------------------------------------------------------------------------------
  2215                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2216                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2217                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2218                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2219                              <1> ;-------------------------------------------------------------------------------
  2220                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2221                              <1> 
  2222                              <1> ;-------------------------------------------------------------------------------
  2223                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2224                              <1> 
  2225                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2226                              <1> ; (unix386.s <-- dsectrm2.s)
  2227                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2228                              <1> 
  2229                              <1> ; 10/12/2014
  2230                              <1> ;
  2231                              <1> ;int40h:
  2232                              <1> ;	pushf
  2233                              <1> ;	push 	cs
  2234                              <1> ;	;cli
  2235                              <1> ;	call 	DISKETTE_IO_1
  2236                              <1> ;	retn
  2237                              <1> 
  2238                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2239                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2240                              <1> ;
  2241                              <1> 
  2242                              <1> ;-- INT13H ---------------------------------------------------------------------
  2243                              <1> ; DISKETTE I/O
  2244                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2245                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2246                              <1> ; INPUT
  2247                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2248                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2249                              <1> ;		ON ALL DRIVES
  2250                              <1> ;------------------------------------------------------------------------------- 
  2251                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2252                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2253                              <1> ;-------------------------------------------------------------------------------
  2254                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2255                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2256                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2257                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2258                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2259                              <1> ;		320/360	320/360	    0-39
  2260                              <1> ;		320/360	1.2M	    0-39
  2261                              <1> ;		1.2M	1.2M	    0-79
  2262                              <1> ;		720K	720K	    0-79
  2263                              <1> ;		1.44M	1.44M	    0-79	
  2264                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2265                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2266                              <1> ;		320/360	320/360	     1-8/9
  2267                              <1> ;		320/360	1.2M	     1-8/9
  2268                              <1> ;		1.2M	1.2M	     1-15
  2269                              <1> ;		720K	720K	     1-9
  2270                              <1> ;		1.44M	1.44M	     1-18		
  2271                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2272                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2273                              <1> ;		320/360	320/360	        8/9
  2274                              <1> ;		320/360	1.2M	        8/9
  2275                              <1> ;		1.2M	1.2M		15
  2276                              <1> ;		720K	720K		9
  2277                              <1> ;		1.44M	1.44M		18
  2278                              <1> ;
  2279                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2280                              <1> ;
  2281                              <1> ;-------------------------------------------------------------------------------
  2282                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2283                              <1> ;-------------------------------------------------------------------------------
  2284                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2285                              <1> ;-------------------------------------------------------------------------------
  2286                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2287                              <1> ;-------------------------------------------------------------------------------
  2288                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2289                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2290                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2291                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2292                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2293                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2294                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2295                              <1> ;		READ/WRITE ACCESS.
  2296                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2297                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2298                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2299                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2300                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2301                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2302                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2303                              <1> ;
  2304                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2305                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2306                              <1> ;		---------------------------------------------
  2307                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2308                              <1> ;		---------------------------------------------
  2309                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2310                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2311                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2312                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2313                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2314                              <1> ;		---------------------------------------------
  2315                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2316                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2317                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2318                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2319                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2320                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2321                              <1> ;-------------------------------------------------------------------------------
  2322                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2323                              <1> ;	REGISTERS
  2324                              <1> ;	  INPUT
  2325                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2326                              <1> ;	  OUTPUT
  2327                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2328                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2329                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2330                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2331                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2332                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2333                              <1> ;	    (BH) - 0
  2334                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2335                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2336                              <1> ;	    (AX) - 0
  2337                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2338                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2339                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2340                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2341                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2342                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2343                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2344                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2345                              <1> ;-------------------------------------------------------------------------------
  2346                              <1> ;	(AH)= 15H  READ DASD TYPE
  2347                              <1> ;	OUTPUT REGISTERS
  2348                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2349                              <1> ;		00 - DRIVE NOT PRESENT	
  2350                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2351                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2352                              <1> ;		03 - RESERVED (FIXED DISK)
  2353                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2354                              <1> ;-------------------------------------------------------------------------------
  2355                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2356                              <1> ;	OUTPUT REGISTERS
  2357                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2358                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2359                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2360                              <1> ;-------------------------------------------------------------------------------
  2361                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2362                              <1> ;	INPUT REGISTERS
  2363                              <1> ;	(AL) -	00 - NOT USED	
  2364                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2365                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2366                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2367                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2368                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2369                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2370                              <1> ;-------------------------------------------------------------------------------
  2371                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2372                              <1> ;	INPUT REGISTERS
  2373                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2374                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2375                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2376                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2377                              <1> ;	OUTPUT REGISTERS:
  2378                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2379                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2380                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2381                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2382                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2383                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2384                              <1> ;-------------------------------------------------------------------------------
  2385                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2386                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2387                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2388                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2389                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2390                              <1> ;		CHANGE ERROR CODE
  2391                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2392                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2393                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2394                              <1> ;
  2395                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2396                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2397                              <1> ;-------------------------------------------------------------------------------
  2398                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2399                              <1> ;	AH = STATUS OF OPERATION
  2400                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2401                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2402                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2403                              <1> ;		TYPE AH=(15)).
  2404                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2405                              <1> ;	FOR READ/WRITE/VERIFY
  2406                              <1> ;		DS,BX,DX,CX PRESERVED
  2407                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2408                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2409                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2410                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2411                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2412                              <1> ;-------------------------------------------------------------------------------
  2413                              <1> ;
  2414                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2415                              <1> ;
  2416                              <1> ;   -----------------------------------------------------------------
  2417                              <1> ;   |       |       |       |       |       |       |       |       |
  2418                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2419                              <1> ;   |       |       |       |       |       |       |       |       |
  2420                              <1> ;   -----------------------------------------------------------------
  2421                              <1> ;	|	|	|	|	|	|	|	|
  2422                              <1> ;	|	|	|	|	|	-----------------
  2423                              <1> ;	|	|	|	|	|		|
  2424                              <1> ;	|	|	|	|    RESERVED		|
  2425                              <1> ;	|	|	|	|		  PRESENT STATE
  2426                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2427                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2428                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2429                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2430                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2431                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2432                              <1> ;	|	|	|	|	110: RESERVED
  2433                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2434                              <1> ;	|	|	|	|
  2435                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2436                              <1> ;	|	|	|
  2437                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2438                              <1> ;	|	|			DRIVE)
  2439                              <1> ;	|	|
  2440                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2441                              <1> ;
  2442                              <1> ;						00: 500 KBS
  2443                              <1> ;						01: 300 KBS
  2444                              <1> ;						10: 250 KBS
  2445                              <1> ;						11: RESERVED
  2446                              <1> ;
  2447                              <1> ;
  2448                              <1> ;-------------------------------------------------------------------------------
  2449                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2450                              <1> ;-------------------------------------------------------------------------------
  2451                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2452                              <1> ;-------------------------------------------------------------------------------
  2453                              <1> 
  2454                              <1> struc MD
  2455 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2456 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2457 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2458 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2459 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2460 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2461 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2462 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2463 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2464 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2465 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2466 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2467 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2468                              <1> endstruc
  2469                              <1> 
  2470                              <1> BIT7OFF	EQU	7FH
  2471                              <1> BIT7ON	EQU	80H
  2472                              <1> 
  2473                              <1> ;;int13h: ; 16/02/2015
  2474                              <1> ;; 16/02/2015 - 21/02/2015
  2475                              <1> int40h:
  2476 0000177B 9C                  <1> 	pushfd
  2477 0000177C 0E                  <1> 	push 	cs
  2478 0000177D E801000000          <1> 	call 	DISKETTE_IO_1
  2479 00001782 C3                  <1> 	retn	
  2480                              <1> 
  2481                              <1> DISKETTE_IO_1:
  2482                              <1> 
  2483 00001783 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2484 00001784 55                  <1> 	PUSH	eBP			; USER REGISTER
  2485 00001785 57                  <1> 	PUSH	eDI			; USER REGISTER
  2486 00001786 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2487 00001787 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2488 00001788 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2489 00001789 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2490                              <1> 					; [BP]   = SECTOR #
  2491                              <1> 					; [BP+1] = TRACK #
  2492                              <1> 					; [BP+2] = BUFFER OFFSET
  2493                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2494                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2495                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2496                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2497                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2498                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2499                              <1> 					; BH/[BP+3] = 0
  2500                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2501                              <1> 					; DH/[BP+5] = MAX HEAD #
  2502                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2503 0000178B 06                  <1> 	push	es ; 06/02/2015	
  2504 0000178C 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2505 0000178D 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2506                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2507                              <1> 	;mov	cx, cs
  2508                              <1> 	;mov	ds, cx
  2509 0000178E 66B91000            <1> 	mov	cx, KDATA
  2510 00001792 8ED9                <1>         mov     ds, cx
  2511 00001794 8EC1                <1>         mov     es, cx
  2512                              <1> 
  2513                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2514 00001796 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2515 00001799 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2516 0000179B B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2517                              <1> OK_FUNC:
  2518 0000179D 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2519 000017A0 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2520 000017A2 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2521 000017A5 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2522 000017A7 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2523 000017AA 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2524 000017AC B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2525                              <1> OK_DRV:
  2526 000017AE 31C9                <1> 	xor	ecx, ecx
  2527                              <1> 	;mov	esi, ecx ; 08/02/2015
  2528                              <1> 	; 24/12/2021
  2529 000017B0 89CE                <1> 	mov	esi, ecx
  2530 000017B2 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2531 000017B4 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2532                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2533                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2534 000017B6 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2535 000017B9 BB[F1170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2536 000017BE 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2537 000017C0 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2538 000017C2 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2539 000017C4 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2540 000017C7 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2541                              <1> 	;
  2542                              <1> 	; 11/12/2014
  2543 000017CA 8815[D1650000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2544                              <1> 	;
  2545 000017D0 8A25[6C6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2546 000017D6 C605[6C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2547                              <1> 
  2548                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2549                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2550                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2551                              <1> ;
  2552                              <1> ;		DI	: DRIVE #
  2553                              <1> ;		SI-HI	: HEAD #
  2554                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2555                              <1> ;		ES	: BUFFER SEGMENT
  2556                              <1> ;		[BP]	: SECTOR #
  2557                              <1> ;		[BP+1]	: TRACK #
  2558                              <1> ;		[BP+2]	: BUFFER OFFSET
  2559                              <1> ;
  2560                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2561                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2562                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2563                              <1> ;	SPECIFIC ERROR CODE.
  2564                              <1> ;
  2565                              <1> 					; (AH) = @DSKETTE_STATUS
  2566 000017DD FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2567 000017DF 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2568 000017E0 1F                  <1> 	POP	DS
  2569 000017E1 07                  <1> 	pop	es	; 06/02/2015
  2570 000017E2 59                  <1> 	POP	eCX
  2571 000017E3 5B                  <1> 	POP	eBX
  2572 000017E4 5A                  <1> 	POP	eDX
  2573 000017E5 5F                  <1> 	POP	eDI
  2574 000017E6 89E5                <1> 	MOV	eBP, eSP
  2575 000017E8 50                  <1> 	PUSH	eAX
  2576 000017E9 9C                  <1> 	PUSHFd
  2577 000017EA 58                  <1> 	POP	eAX
  2578                              <1> 	;MOV	[BP+6], AX
  2579 000017EB 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2580 000017EE 58                  <1> 	POP	eAX
  2581 000017EF 5D                  <1> 	POP	eBP
  2582 000017F0 CF                  <1> 	IRETd
  2583                              <1> 
  2584                              <1> ;-------------------------------------------------------------------------------
  2585                              <1> ; DW --> dd (06/02/2015)
  2586 000017F1 [55180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2587 000017F5 [CA180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2588 000017F9 [DA180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2589 000017FD [EB180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2590 00001801 [FC180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2591 00001805 [0D190000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2592 00001809 [91190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2593 0000180D [91190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2594 00001811 [9D190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2595 00001815 [91190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2596 00001819 [91190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2597 0000181D [91190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2598 00001821 [91190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2599 00001825 [91190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2600 00001829 [91190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2601 0000182D [91190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2602 00001831 [91190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2603 00001835 [91190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2604 00001839 [91190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2605 0000183D [91190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2606 00001841 [91190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2607 00001845 [5C1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2608 00001849 [841A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2609 0000184D [BD1A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2610 00001851 [3E1B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2611                              <1> FNC_TAE EQU     $                       ; END
  2612                              <1> 
  2613                              <1> ;-------------------------------------------------------------------------------
  2614                              <1> ; DISK_RESET	(AH = 00H)	
  2615                              <1> ;		RESET THE DISKETTE SYSTEM.
  2616                              <1> ;
  2617                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2618                              <1> ;-------------------------------------------------------------------------------
  2619                              <1> DSK_RESET:
  2620 00001855 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2621 00001859 FA                  <1> 	CLI				; NO INTERRUPTS
  2622 0000185A A0[6A6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2623 0000185F 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2624 00001861 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2625                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2626 00001864 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2627 00001866 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2628 00001867 C605[696B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2629                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2630                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2631                              <1> 					;      PULSE WIDTH)
  2632                              <1> 	; 19/12/2014
  2633                              <1> 	NEWIODELAY
  2106 0000186E E6EB                <2>  out 0EBh,al
  2634                              <1> 
  2635                              <1> 	; 17/12/2014 
  2636                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2637 00001870 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2638                              <1> wdw1:
  2639                              <1> 	NEWIODELAY   ; 27/02/2015
  2106 00001875 E6EB                <2>  out 0EBh,al
  2640 00001877 E2FC                <1> 	loop	wdw1
  2641                              <1> 	;
  2642 00001879 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2643 0000187B EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2644                              <1> 	; 16/12/2014
  2645                              <1> 	IODELAY
  2101 0000187C EB00                <2>  jmp short $+2
  2102 0000187E EB00                <2>  jmp short $+2
  2646                              <1> 	;
  2647                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2648 00001880 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2649 00001885 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2650 00001887 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2651                              <1> NXT_DRV:
  2652                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2653                              <1> 	; 24/12/2021
  2654 0000188B 51                  <1> 	push	ecx
  2655 0000188C B8[C0180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2656 00001891 50                  <1> 	PUSH	eAX			; "
  2657 00001892 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2658 00001894 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2659 00001899 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2660 0000189A E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2661                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2662                              <1> 	; 24/12/2021
  2663 0000189F 59                  <1> 	pop	ecx
  2664 000018A0 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2665 000018A2 3A0D[6D6B0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2666 000018A8 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2667 000018AA FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2668 000018AC 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2669 000018AF 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2670                              <1> 	;
  2671 000018B1 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2672                              <1> RESBAC:
  2673 000018B6 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2674                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2675                              <1> 	; 24/12/2021
  2676 000018BB 89F3                <1> 	mov	ebx, esi
  2677 000018BD 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2678 000018BF C3                  <1> 	RETn		
  2679                              <1> DR_POP_ERR:
  2680                              <1> 	;POP	CX			; CLEAR STACK
  2681                              <1> 	; 24/12/2021
  2682 000018C0 59                  <1> 	pop	ecx
  2683                              <1> DR_ERR:
  2684 000018C1 800D[6C6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2685 000018C8 EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2686                              <1> 
  2687                              <1> ;-------------------------------------------------------------------------------
  2688                              <1> ; DISK_STATUS	(AH = 01H)
  2689                              <1> ;	DISKETTE STATUS.
  2690                              <1> ;
  2691                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2692                              <1> ;
  2693                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2694                              <1> ;-------------------------------------------------------------------------------
  2695                              <1> DSK_STATUS:
  2696 000018CA 8825[6C6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2697 000018D0 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2698                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2699                              <1> 	; 24/12/2021
  2700 000018D5 89F3                <1> 	mov	ebx, esi
  2701 000018D7 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2702 000018D9 C3                  <1> 	RETn		
  2703                              <1> 
  2704                              <1> ;-------------------------------------------------------------------------------
  2705                              <1> ; DISK_READ	(AH = 02H)	
  2706                              <1> ;	DISKETTE READ.
  2707                              <1> ;
  2708                              <1> ; ON ENTRY:	DI	: DRIVE #
  2709                              <1> ;		SI-HI	: HEAD #
  2710                              <1> ;		SI-LOW	: # OF SECTORS
  2711                              <1> ;		ES	: BUFFER SEGMENT
  2712                              <1> ;		[BP]	: SECTOR #
  2713                              <1> ;		[BP+1]	: TRACK #
  2714                              <1> ;		[BP+2]	: BUFFER OFFSET
  2715                              <1> ;
  2716                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2717                              <1> ;-------------------------------------------------------------------------------
  2718                              <1> 
  2719                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2720                              <1> 
  2721                              <1> DSK_READ:
  2722 000018DA 8025[6A6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2723 000018E1 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2724 000018E5 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2725 000018EA C3                  <1> 	RETn
  2726                              <1> 
  2727                              <1> ;-------------------------------------------------------------------------------
  2728                              <1> ; DISK_WRITE	(AH = 03H)
  2729                              <1> ;	DISKETTE WRITE.
  2730                              <1> ;
  2731                              <1> ; ON ENTRY:	DI	: DRIVE #
  2732                              <1> ;		SI-HI	: HEAD #
  2733                              <1> ;		SI-LOW	: # OF SECTORS
  2734                              <1> ;		ES	: BUFFER SEGMENT
  2735                              <1> ;		[BP]	: SECTOR #
  2736                              <1> ;		[BP+1]	: TRACK #
  2737                              <1> ;		[BP+2]	: BUFFER OFFSET
  2738                              <1> ;
  2739                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2740                              <1> ;-------------------------------------------------------------------------------
  2741                              <1> 
  2742                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2743                              <1> 
  2744                              <1> DSK_WRITE:
  2745 000018EB 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2746 000018EF 800D[6A6B0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2747 000018F6 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2748 000018FB C3                  <1> 	RETn
  2749                              <1> 
  2750                              <1> ;-------------------------------------------------------------------------------
  2751                              <1> ; DISK_VERF	(AH = 04H)
  2752                              <1> ;	DISKETTE VERIFY.
  2753                              <1> ;
  2754                              <1> ; ON ENTRY:	DI	: DRIVE #
  2755                              <1> ;		SI-HI	: HEAD #
  2756                              <1> ;		SI-LOW	: # OF SECTORS
  2757                              <1> ;		ES	: BUFFER SEGMENT
  2758                              <1> ;		[BP]	: SECTOR #
  2759                              <1> ;		[BP+1]	: TRACK #
  2760                              <1> ;		[BP+2]	: BUFFER OFFSET
  2761                              <1> ;
  2762                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2763                              <1> ;-------------------------------------------------------------------------------
  2764                              <1> DSK_VERF:
  2765 000018FC 8025[6A6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2766 00001903 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2767 00001907 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2768 0000190C C3                  <1> 	RETn
  2769                              <1> 
  2770                              <1> ;-------------------------------------------------------------------------------
  2771                              <1> ; DISK_FORMAT	(AH = 05H)
  2772                              <1> ;	DISKETTE FORMAT.
  2773                              <1> ;
  2774                              <1> ; ON ENTRY:	DI	: DRIVE #
  2775                              <1> ;		SI-HI	: HEAD #
  2776                              <1> ;		SI-LOW	: # OF SECTORS
  2777                              <1> ;		ES	: BUFFER SEGMENT
  2778                              <1> ;		[BP]	: SECTOR #
  2779                              <1> ;		[BP+1]	: TRACK #
  2780                              <1> ;		[BP+2]	: BUFFER OFFSET
  2781                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2782                              <1> ;
  2783                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2784                              <1> ;-------------------------------------------------------------------------------
  2785                              <1> DSK_FORMAT:
  2786 0000190D E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2787 00001912 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2788 00001917 800D[6A6B0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2789 0000191E E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2790 00001923 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2791 00001925 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2792 0000192A E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2793 0000192F 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2794 00001931 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2795                              <1> FM_WR:
  2796 00001936 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2797 0000193B 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2798 0000193D B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2799 0000193F E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2800 00001944 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2801 00001946 B8[82190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2802 0000194B 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2803 0000194C B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2804 0000194E E80E090000          <1> 	CALL	GET_PARM
  2805 00001953 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2806 00001958 B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2807 0000195A E802090000          <1> 	CALL	GET_PARM
  2808 0000195F E8030A0000          <1> 	CALL	NEC_OUTPUT
  2809 00001964 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2810 00001966 E8F6080000          <1> 	CALL	GET_PARM
  2811 0000196B E8F7090000          <1> 	CALL	NEC_OUTPUT
  2812 00001970 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2813 00001972 E8EA080000          <1> 	CALL	GET_PARM
  2814 00001977 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2815 0000197C 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2816 0000197D E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2817                              <1> FM_DON:
  2818 00001982 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2819 00001987 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2820                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2821 0000198C 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2822 0000198E 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2823 00001990 C3                  <1> 	RETn
  2824                              <1> 
  2825                              <1> ;-------------------------------------------------------------------------------
  2826                              <1> ; FNC_ERR
  2827                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2828                              <1> ;	SET BAD COMMAND IN STATUS.
  2829                              <1> ;
  2830                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2831                              <1> ;-------------------------------------------------------------------------------
  2832                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2833                              <1> 	;MOV	AX,SI			; RESTORE AL
  2834                              <1> 	; 24/12/2021
  2835 00001991 89F0                <1> 	mov	eax, esi
  2836 00001993 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2837 00001995 8825[6C6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2838 0000199B F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2839 0000199C C3                  <1> 	RETn
  2840                              <1> 
  2841                              <1> ;-------------------------------------------------------------------------------
  2842                              <1> ; DISK_PARMS	(AH = 08H)	
  2843                              <1> ;	READ DRIVE PARAMETERS.
  2844                              <1> ;
  2845                              <1> ; ON ENTRY:	DI : DRIVE #
  2846                              <1> ;
  2847                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2848                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2849                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2850                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2851                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2852                              <1> ;		BH/[BP+3] = 0
  2853                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2854                              <1> ;		DH/[BP+5] = MAX HEAD #
  2855                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2856                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2857                              <1> ;		AX        = 0
  2858                              <1> ;
  2859                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2860                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2861                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2862                              <1> ;		       CALLER.
  2863                              <1> ;-------------------------------------------------------------------------------
  2864                              <1> DSK_PARMS:
  2865 0000199D E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2866                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2867 000019A2 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2868 000019A4 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2869                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2870                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2871                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2872                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2873                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2874                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2875                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2876                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2877                              <1> 	;sub	edx, edx
  2878 000019A7 66A1[DE650000]      <1> 	mov     ax, [fd0_type]
  2879 000019AD 6621C0              <1> 	and     ax, ax
  2880 000019B0 7473                <1> 	jz      short NON_DRV
  2881 000019B2 FEC2                <1> 	inc     dl
  2882 000019B4 20E4                <1> 	and     ah, ah
  2883 000019B6 7402                <1> 	jz      short STO_DL
  2884 000019B8 FEC2                <1> 	inc     dl
  2885                              <1> STO_DL:
  2886                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2887 000019BA 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2888 000019BD 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2889 000019C1 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2890                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2891 000019C3 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2892 000019C7 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2893                              <1> 	;;20/02/2015
  2894                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2895                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2896 000019CC 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2897 000019CE E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2898 000019D3 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2899                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2900 000019D5 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2901 000019D8 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2902 000019DB 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2903 000019DE EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2904                              <1> CHK_EST:
  2905 000019E0 8AA7[796B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2906 000019E6 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2907 000019E9 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2908                              <1> USE_EST:
  2909 000019EB 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2910 000019EE 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2911 000019F1 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2912                              <1> 
  2913                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2914                              <1> 
  2915 000019F3 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2916 000019F5 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2917 000019FA 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2918 000019FD 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2919 00001A00 F687[796B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2920 00001A07 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2921                              <1> 
  2922                              <1> ;-----	IT IS 1.44 MB DRIVE
  2923                              <1> 
  2924                              <1> PARM144:
  2925 00001A09 B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2926 00001A0B E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2927 00001A10 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2928 00001A13 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2929                              <1> STO_CX:
  2930 00001A16 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2931                              <1> ES_DI:
  2932                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2933 00001A19 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2934                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2935                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2936                              <1> DP_OUT:
  2937 00001A1C E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2938                              <1> 	;XOR	AX,AX			; CLEAR
  2939                              <1> 	; 24/12/2021
  2940 00001A21 31C0                <1> 	xor	eax, eax
  2941 00001A23 F8                  <1> 	CLC
  2942 00001A24 C3                  <1> 	RETn
  2943                              <1> 
  2944                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2945                              <1> 
  2946                              <1> NON_DRV:
  2947                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2948 00001A25 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2949                              <1> NON_DRV1:
  2950 00001A28 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2951 00001A2D 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2952                              <1> 
  2953                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2954                              <1> 	
  2955 00001A2F E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2956                              <1> 	;MOV	AX,SI			; RESTORE AL
  2957 00001A34 89F0                <1> 	mov	eax, esi ; 24/12/2021
  2958 00001A36 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2959 00001A38 F9                  <1> 	STC
  2960 00001A39 C3                  <1> 	RETn
  2961                              <1> 
  2962                              <1> NON_DRV2:
  2963                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2964 00001A3A 31C0                <1> 	xor	eax, eax	
  2965 00001A3C 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2966                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2967 00001A40 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2968                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2969 00001A43 89450C              <1> 	mov	[ebp+12], eax
  2970                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2971 00001A46 EBD4                <1> 	JMP	SHORT DP_OUT
  2972                              <1> 
  2973                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  2974                              <1> 
  2975                              <1> USE_EST2:
  2976 00001A48 B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  2977 00001A4A E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2978 00001A4F 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2979 00001A52 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2980 00001A55 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  2981 00001A58 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  2982 00001A5A EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  2983                              <1> 
  2984                              <1> ;-------------------------------------------------------------------------------
  2985                              <1> ; DISK_TYPE (AH = 15H)	
  2986                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  2987                              <1> ;
  2988                              <1> ;  ON ENTRY:	DI = DRIVE #
  2989                              <1> ;
  2990                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  2991                              <1> ;-------------------------------------------------------------------------------
  2992                              <1> DSK_TYPE:
  2993 00001A5C E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2994 00001A61 8A87[796B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  2995 00001A67 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  2996 00001A69 7415                <1> 	JZ	short NO_DRV
  2997 00001A6B B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  2998 00001A6D A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  2999 00001A6F 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3000 00001A71 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3001                              <1> DT_BACK:
  3002                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3003 00001A73 50                  <1> 	push	eax ; 24/12/2021
  3004 00001A74 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3005                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3006 00001A79 58                  <1> 	pop	eax ; 24/12/2021
  3007 00001A7A F8                  <1> 	CLC				; NO ERROR
  3008                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3009                              <1> 	; 24/12/2021
  3010 00001A7B 89F3                <1> 	mov	ebx, esi
  3011 00001A7D 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3012 00001A7F C3                  <1> 	RETn
  3013                              <1> NO_DRV:	
  3014 00001A80 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3015 00001A82 EBEF                <1> 	JMP	SHORT DT_BACK
  3016                              <1> 
  3017                              <1> ;-------------------------------------------------------------------------------
  3018                              <1> ; DISK_CHANGE	(AH = 16H)
  3019                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3020                              <1> ;
  3021                              <1> ; ON ENTRY:	DI = DRIVE #
  3022                              <1> ;
  3023                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3024                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3025                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3026                              <1> ;-------------------------------------------------------------------------------
  3027                              <1> DSK_CHANGE:
  3028 00001A84 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3029 00001A89 8A87[796B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3030 00001A8F 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3031 00001A91 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3032 00001A93 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3033 00001A95 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3034                              <1> DC0:
  3035 00001A97 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3036 00001A9C 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3037                              <1> 
  3038 00001A9E C605[6C6B0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3039                              <1> 
  3040 00001AA5 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3041 00001AAA E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3042                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3043                              <1> 	; 24/12/2021
  3044 00001AAF 89F3                <1> 	mov	ebx, esi
  3045 00001AB1 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3046 00001AB3 C3                  <1> 	RETn
  3047                              <1> DC_NON:
  3048 00001AB4 800D[6C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3049 00001ABB EBE8                <1> 	JMP	SHORT FINIS
  3050                              <1> 
  3051                              <1> ;-------------------------------------------------------------------------------
  3052                              <1> ; FORMAT_SET	(AH = 17H)
  3053                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3054                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3055                              <1> ;
  3056                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3057                              <1> ;		DI     = DRIVE #
  3058                              <1> ;
  3059                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3060                              <1> ;		AH = @DSKETTE_STATUS
  3061                              <1> ;		CY = 1 IF ERROR
  3062                              <1> ;-------------------------------------------------------------------------------
  3063                              <1> FORMAT_SET:
  3064 00001ABD E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3065                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3066                              <1> 	; 24/12/2021
  3067 00001AC2 56                  <1> 	push	esi
  3068 00001AC3 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3069 00001AC6 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3070 00001AC8 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3071 00001ACB 80A7[796B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3072 00001AD2 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3073 00001AD4 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3074 00001AD6 808F[796B0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3075 00001ADD EB48                <1> 	JMP	SHORT S0
  3076                              <1> NOT_320:
  3077 00001ADF E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3078 00001AE4 803D[6C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3079 00001AEB 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3080                              <1> S3:
  3081 00001AED 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3082 00001AEF 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3083 00001AF1 808F[796B0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3084 00001AF8 EB2D                <1> 	JMP	SHORT S0
  3085                              <1> NOT_320_12:
  3086 00001AFA 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3087 00001AFC 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3088 00001AFE 808F[796B0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3089 00001B05 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3090                              <1> NOT_12:	
  3091 00001B07 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3092 00001B09 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3093                              <1> 
  3094 00001B0B F687[796B0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3095 00001B12 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3096 00001B14 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3097 00001B16 F687[796B0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3098 00001B1D 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3099                              <1> ASSUME:
  3100 00001B1F B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3101                              <1> OR_IT_IN:
  3102 00001B21 0887[796B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3103                              <1> S0:
  3104 00001B27 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3105 00001B2C E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3106                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3107                              <1> 	; 24/12/2021
  3108 00001B31 5B                  <1> 	pop	ebx
  3109 00001B32 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3110 00001B34 C3                  <1> 	RETn
  3111                              <1> FS_ERR:
  3112 00001B35 C605[6C6B0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3113 00001B3C EBE9                <1> 	JMP	SHORT S0
  3114                              <1> 
  3115                              <1> ;-------------------------------------------------------------------------------
  3116                              <1> ; SET_MEDIA	(AH = 18H)
  3117                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3118                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3119                              <1> ;
  3120                              <1> ; ON ENTRY:
  3121                              <1> ;	[BP]	= SECTOR PER TRACK
  3122                              <1> ;	[BP+1]	= TRACK #
  3123                              <1> ;	DI	= DRIVE #
  3124                              <1> ;
  3125                              <1> ; ON EXIT:
  3126                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3127                              <1> ;	IF NO ERROR:
  3128                              <1> ;		AH = 0
  3129                              <1> ;		CY = 0
  3130                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3131                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3132                              <1> ;	IF ERROR:	
  3133                              <1> ;		AH = @DSKETTE_STATUS
  3134                              <1> ;		CY = 1
  3135                              <1> ;-------------------------------------------------------------------------------
  3136                              <1> SET_MEDIA:
  3137 00001B3E E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3138 00001B43 F687[796B0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3139 00001B4A 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3140 00001B4C E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3141 00001B51 803D[6C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3142 00001B58 746B                <1> 	JE	short SM_RTN
  3143 00001B5A C605[6C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3144                              <1> SM_CMOS:
  3145 00001B61 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3146                              <1> 	;;20/02/2015
  3147                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3148                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3149 00001B66 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3150 00001B68 E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3151 00001B6D 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3152 00001B6F 57                  <1> 	PUSH	eDI			; SAVE REG.
  3153 00001B70 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3154 00001B72 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3155                              <1> DR_SEARCH:
  3156 00001B77 8AA3[5C650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3157 00001B7D 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3158 00001B80 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3159 00001B82 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3160                              <1> DR_FND:
  3161 00001B84 8BBB[5D650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3162                              <1> MD_SEARCH:
  3163 00001B8A 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3164 00001B8D 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3165 00001B90 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3166 00001B92 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3167 00001B95 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3168 00001B98 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3169                              <1> NXT_MD:
  3170                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3171 00001B9A 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3172 00001B9D E2D8                <1> 	LOOP    DR_SEARCH
  3173 00001B9F 5F                  <1> 	POP	eDI			; RESTORE REG.
  3174                              <1> MD_NOT_FND:
  3175 00001BA0 C605[6C6B0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3176 00001BA7 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3177                              <1> MD_FND:
  3178 00001BA9 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3179 00001BAC 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3180 00001BAE 7502                <1> 	JNE	short MD_SET
  3181 00001BB0 0C20                <1> 	OR	AL,DBL_STEP
  3182                              <1> MD_SET:
  3183                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3184 00001BB2 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3185 00001BB5 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3186 00001BB7 5F                  <1> 	POP	eDI
  3187 00001BB8 80A7[796B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3188 00001BBF 0887[796B0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3189                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3190                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3191                              <1> SM_RTN:
  3192 00001BC5 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3193 00001BCA E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3194 00001BCF C3                  <1> 	RETn
  3195                              <1> 
  3196                              <1> ;----------------------------------------------------------------
  3197                              <1> ; DR_TYPE_CHECK							:
  3198                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3199                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3200                              <1> ; ON ENTRY:							:
  3201                              <1> ;	AL = DRIVE TYPE						:
  3202                              <1> ; ON EXIT:							:
  3203                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3204                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3205                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3206                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3207                              <1> ; REGISTERS ALTERED: eBX						:
  3208                              <1> ;----------------------------------------------------------------		
  3209                              <1> DR_TYPE_CHECK:
  3210                              <1> 	;PUSH	AX			
  3211                              <1> 	; 24/12/2021
  3212 00001BD0 50                  <1> 	push	eax
  3213 00001BD1 51                  <1> 	PUSH	eCX
  3214 00001BD2 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3215 00001BD4 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3216                              <1> TYPE_CHK:	
  3217 00001BD9 8AA3[5C650000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3218 00001BDF 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3219 00001BE1 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3220                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3221 00001BE3 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3222 00001BE6 E2F1                <1> 	LOOP    TYPE_CHK
  3223                              <1> 	;
  3224 00001BE8 BB[BB650000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3225                              <1> 					; Default for GET_PARM (11/12/2014)
  3226                              <1> 	;
  3227 00001BED F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3228 00001BEE EB06                <1> 	JMP	SHORT TYPE_RTN
  3229                              <1> DR_TYPE_VALID:
  3230 00001BF0 8B9B[5D650000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3231                              <1> TYPE_RTN:
  3232 00001BF6 59                  <1> 	POP	eCX
  3233                              <1> 	;POP	AX
  3234                              <1> 	; 24/12/2021
  3235 00001BF7 58                  <1> 	pop	eax
  3236 00001BF8 C3                  <1> 	RETn	
  3237                              <1> 		
  3238                              <1> ;----------------------------------------------------------------
  3239                              <1> ; SEND_SPEC							:
  3240                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3241                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3242                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3243                              <1> ; ON EXIT:	NONE						:	
  3244                              <1> ; REGISTERS ALTERED: CX, DX					:
  3245                              <1> ;----------------------------------------------------------------		
  3246                              <1> SEND_SPEC:
  3247 00001BF9 50                  <1> 	PUSH	eAX			; SAVE AX
  3248 00001BFA B8[201C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3249 00001BFF 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3250 00001C00 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3251 00001C02 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3252 00001C07 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3253 00001C09 E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3254 00001C0E E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3255 00001C13 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3256 00001C15 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3257 00001C1A E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3258 00001C1F 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3259                              <1> SPECBAC:
  3260 00001C20 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3261 00001C21 C3                  <1> 	RETn
  3262                              <1> 
  3263                              <1> ;----------------------------------------------------------------
  3264                              <1> ; SEND_SPEC_MD							:
  3265                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3266                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3267                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3268                              <1> ; ON EXIT:	NONE						:	
  3269                              <1> ; REGISTERS ALTERED: AX						:
  3270                              <1> ;----------------------------------------------------------------		
  3271                              <1> SEND_SPEC_MD:
  3272 00001C22 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3273 00001C23 B8[401C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3274 00001C28 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3275 00001C29 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3276 00001C2B E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3277 00001C30 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3278 00001C32 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3279 00001C37 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3280 00001C3A E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3281 00001C3F 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3282                              <1> SPEC_ESBAC:
  3283 00001C40 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3284 00001C41 C3                  <1> 	RETn
  3285                              <1> 
  3286                              <1> ;-------------------------------------------------------------------------------
  3287                              <1> ; XLAT_NEW  
  3288                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3289                              <1> ;	MODE TO NEW ARCHITECTURE.
  3290                              <1> ;
  3291                              <1> ; ON ENTRY:	DI = DRIVE #
  3292                              <1> ;-------------------------------------------------------------------------------
  3293                              <1> XLAT_NEW:
  3294 00001C42 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3295 00001C45 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3296 00001C47 80BF[796B0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3297 00001C4E 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3298 00001C50 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3299 00001C53 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3300 00001C56 A0[786B0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3301 00001C5B D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3302 00001C5D 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3303 00001C5F 80A7[796B0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3304 00001C66 0887[796B0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3305                              <1> XN_OUT:
  3306 00001C6C C3                  <1> 	RETn
  3307                              <1> DO_DET:
  3308 00001C6D E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3309 00001C72 C3                  <1> 	RETn
  3310                              <1> 
  3311                              <1> ;-------------------------------------------------------------------------------
  3312                              <1> ; XLAT_OLD 
  3313                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3314                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3315                              <1> ;
  3316                              <1> ; ON ENTRY:	DI = DRIVE
  3317                              <1> ;-------------------------------------------------------------------------------
  3318                              <1> XLAT_OLD:
  3319 00001C73 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3320                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3321                              <1>         ;ja	XO_OUT
  3322                              <1>         ; 24/12/2021
  3323 00001C76 77F4                <1> 	ja	short XN_OUT
  3324 00001C78 80BF[796B0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3325 00001C7F 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3326                              <1> 
  3327                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3328                              <1> 
  3329 00001C81 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3330 00001C84 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3331 00001C87 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3332 00001C89 D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3333 00001C8B 8425[786B0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3334 00001C91 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3335                              <1> 
  3336                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3337                              <1> 
  3338 00001C93 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3339 00001C95 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3340 00001C97 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3341 00001C99 2025[786B0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3342                              <1> 
  3343                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3344                              <1> 
  3345 00001C9F 8A87[796B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3346 00001CA5 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3347 00001CA7 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3348 00001CA9 0805[786B0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3349                              <1> 
  3350                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3351                              <1> 
  3352                              <1> SAVE_SET:
  3353 00001CAF 8AA7[796B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3354 00001CB5 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3355 00001CB7 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3356 00001CBA 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3357 00001CBD 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3358 00001CBF B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3359 00001CC1 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3360 00001CC4 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3361 00001CC6 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3362 00001CC9 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3363                              <1> UNKNO:
  3364 00001CCB B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3365 00001CCD EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3366                              <1> CHK_144:
  3367 00001CCF E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3368                              <1> 	;;20/02/2015
  3369                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3370 00001CD4 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3371 00001CD6 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3372 00001CD8 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3373 00001CDA B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3374 00001CDC EB0C                <1> 	JMP	SHORT TST_DET
  3375                              <1> CHK_250:
  3376 00001CDE B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3377 00001CE0 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3378 00001CE3 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3379 00001CE5 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3380 00001CE8 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3381                              <1> TST_DET:
  3382 00001CEA F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3383 00001CED 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3384 00001CEF 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3385                              <1> AL_SET:
  3386 00001CF1 80A7[796B0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3387 00001CF8 0887[796B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3388                              <1> XO_OUT:
  3389 00001CFE C3                  <1> 	RETn
  3390                              <1> 
  3391                              <1> ;-------------------------------------------------------------------------------
  3392                              <1> ; RD_WR_VF
  3393                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3394                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3395                              <1> ;
  3396                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3397                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3398                              <1> ;
  3399                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3400                              <1> ;-------------------------------------------------------------------------------
  3401                              <1> RD_WR_VF:
  3402                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3403 00001CFF 50                  <1> 	push	eax ; 24/12/2021
  3404 00001D00 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3405 00001D05 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3406                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3407 00001D0A 58                  <1> 	pop	eax ; 24/12/2021
  3408                              <1> DO_AGAIN:
  3409                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3410 00001D0B 50                  <1> 	push	eax ; 24/12/2021
  3411 00001D0C E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3412                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3413 00001D11 58                  <1> 	pop	eax ; 24/12/2021
  3414                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3415                              <1> 	; 24/12/2021
  3416 00001D12 7305                <1> 	jnc	short RWV
  3417 00001D14 E9C3000000          <1> 	jmp	RWV_END
  3418                              <1> RWV:
  3419                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3420 00001D19 50                  <1> 	push	eax ; 24/12/2021
  3421 00001D1A 8AB7[796B0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3422 00001D20 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3423 00001D23 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3424                              <1> 	;;20/02/2015
  3425                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3426 00001D28 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3427 00001D2A 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3428 00001D2C 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3429 00001D2E F687[796B0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3430 00001D35 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3431 00001D37 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3432 00001D39 EB0F                <1> 	JMP	SHORT RWV_2
  3433                              <1> RWV_1:
  3434 00001D3B 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3435 00001D3D F687[796B0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3436 00001D44 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3437 00001D46 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3438 00001D48 EB04                <1> 	jmp	short rwv_3
  3439                              <1> RWV_2:
  3440 00001D4A 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3441 00001D4C 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3442                              <1> rwv_3:
  3443 00001D4E E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3444 00001D53 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3445                              <1> 
  3446                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3447                              <1> 
  3448 00001D55 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3449 00001D56 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3450 00001D58 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3451                              <1> RWV_DR_SEARCH:
  3452 00001D5D 8AA3[5C650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3453 00001D63 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3454 00001D66 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3455 00001D68 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3456                              <1> RWV_DR_FND:
  3457 00001D6A 8BBB[5D650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3458                              <1> RWV_MD_SEARH:
  3459 00001D70 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3460 00001D73 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3461                              <1> RWV_NXT_MD:
  3462                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3463 00001D75 83C305              <1> 	add	eBX, 5
  3464 00001D78 E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3465 00001D7A 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3466                              <1> 
  3467                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3468                              <1> 
  3469                              <1> RWV_ASSUME:
  3470 00001D7B BB[7A650000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3471 00001D80 F687[796B0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3472 00001D87 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3473 00001D89 BB[94650000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3474 00001D8E EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3475                              <1> 
  3476                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3477                              <1> 	 			
  3478                              <1> RWV_MD_FND:
  3479 00001D90 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3480 00001D92 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3481                              <1> 	
  3482                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3483                              <1> 
  3484                              <1> RWV_MD_FND1:
  3485 00001D93 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3486 00001D98 E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3487 00001D9D 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3488 00001D9F E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3489                              <1> RWV_DBL:
  3490 00001DA4 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3491 00001DA5 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3492 00001DAA 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3493 00001DAB 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3494                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3495 00001DAD 58                  <1> 	pop	eax ; 24/12/2021
  3496                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3497 00001DAE 50                  <1> 	push	eax ; 24/12/2021
  3498 00001DAF 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3499 00001DB0 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3500 00001DB5 5B                  <1> 	POP	eBX 
  3501                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3502 00001DB6 58                  <1> 	pop	eax ; 24/12/2021
  3503 00001DB7 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3504                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3505 00001DB9 50                  <1> 	push	eax ; 24/12/2021
  3506 00001DBA 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3507 00001DBB E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3508 00001DC0 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3509 00001DC1 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3510 00001DC3 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3511 00001DC8 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3512 00001DCA E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3513                              <1> CHK_RET:
  3514 00001DCF E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3515                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3516 00001DD4 58                  <1> 	pop	eax ; 24/12/2021
  3517 00001DD5 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3518 00001DD7 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3519                              <1> RWV_END:
  3520 00001DDC E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3521 00001DE1 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3522                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3523                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3524 00001DE6 50                  <1> 	push	eax ; 24/12/2021
  3525 00001DE7 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3526                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3527 00001DEC 58                  <1> 	pop	eax ; 24/12/2021
  3528 00001DED E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3529 00001DF2 C3                  <1> 	RETn
  3530                              <1> 
  3531                              <1> ;-------------------------------------------------------------------------------
  3532                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3533                              <1> ;-------------------------------------------------------------------------------
  3534                              <1> SETUP_STATE:
  3535 00001DF3 F687[796B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3536 00001DFA 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3537 00001DFC 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3538 00001E00 F687[796B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3539 00001E07 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3540 00001E09 F687[796B0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3541 00001E10 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3542 00001E12 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3543                              <1> AX_SET:	
  3544 00001E16 80A7[796B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3545 00001E1D 08A7[796B0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3546 00001E23 8025[746B0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3547 00001E2A C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3548 00001E2D 0805[746B0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3549                              <1> J1C:	
  3550 00001E33 C3                  <1> 	RETn
  3551                              <1> 
  3552                              <1> ;-------------------------------------------------------------------------------
  3553                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3554                              <1> ;-------------------------------------------------------------------------------
  3555                              <1> FMT_INIT:
  3556 00001E34 F687[796B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3557 00001E3B 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3558 00001E3D E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3559                              <1> 	;; 20/02/2015
  3560                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3561 00001E42 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3562 00001E44 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3563                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3564 00001E46 8AA7[796B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3565 00001E4C 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3566 00001E4F 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3567 00001E51 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3568 00001E53 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3569 00001E56 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3570                              <1> N_360:	
  3571 00001E58 FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3572 00001E5A 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3573                              <1> F1_RATE:
  3574 00001E5C 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3575 00001E5F EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3576                              <1> N_12:	
  3577 00001E61 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3578 00001E63 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3579 00001E65 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3580 00001E68 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3581 00001E6A F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3582 00001E6D 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3583 00001E6F 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3584 00001E72 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3585                              <1> N_720:
  3586 00001E74 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3587 00001E76 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3588 00001E78 EBE2                <1> 	JMP	SHORT F1_RATE
  3589                              <1> ISNT_12: 
  3590 00001E7A 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3591                              <1> 
  3592                              <1> SKP_STATE:
  3593 00001E7D 88A7[796B0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3594                              <1> F1_OUT:
  3595 00001E83 C3                  <1> 	RETn
  3596                              <1> CL_DRV:	
  3597 00001E84 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3598 00001E86 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3599                              <1> 
  3600                              <1> ;-------------------------------------------------------------------------------
  3601                              <1> ; MED_CHANGE	
  3602                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3603                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3604                              <1> ;
  3605                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3606                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3607                              <1> ;-------------------------------------------------------------------------------
  3608                              <1> MED_CHANGE:
  3609 00001E88 E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3610 00001E8D 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3611 00001E8F 80A7[796B0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3612                              <1> 
  3613                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3614                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3615                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3616                              <1> 
  3617 00001E96 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3618 00001E99 B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3619 00001E9B D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3620 00001E9D F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3621 00001E9F FA                  <1> 	CLI				; NO INTERRUPTS
  3622 00001EA0 2005[6A6B0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3623 00001EA6 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3624 00001EA7 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3625                              <1> 
  3626                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3627                              <1> 
  3628 00001EAC E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3629 00001EB1 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3630 00001EB3 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3631 00001EB8 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3632 00001EBA E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3633 00001EBF C605[6C6B0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3634                              <1> OK1:
  3635 00001EC6 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3636 00001ECB 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3637                              <1> OK4:
  3638 00001ECD C605[6C6B0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3639                              <1> OK2:		
  3640 00001ED4 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3641 00001ED5 C3                  <1> 	RETn
  3642                              <1> MC_OUT:
  3643 00001ED6 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3644 00001ED7 C3                  <1> 	RETn
  3645                              <1> 
  3646                              <1> ;-------------------------------------------------------------------------------
  3647                              <1> ; SEND_RATE
  3648                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3649                              <1> ; ON ENTRY:	DI = DRIVE #
  3650                              <1> ; ON EXIT:	NONE
  3651                              <1> ; REGISTERS ALTERED: DX
  3652                              <1> ;-------------------------------------------------------------------------------
  3653                              <1> SEND_RATE:
  3654                              <1> 	;PUSH	AX			; SAVE REG.
  3655                              <1> 	; 24/12/2021
  3656 00001ED8 50                  <1> 	push	eax
  3657 00001ED9 8025[746B0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3658 00001EE0 8A87[796B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3659 00001EE6 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3660 00001EE8 0805[746B0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3661 00001EEE C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3662 00001EF1 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3663 00001EF5 EE                  <1> 	OUT	DX,AL
  3664                              <1> 	;POP	AX			; RESTORE REG.
  3665                              <1> 	; 24/12/2021
  3666 00001EF6 58                  <1> 	pop	eax
  3667 00001EF7 C3                  <1> 	RETn
  3668                              <1> 
  3669                              <1> ;-------------------------------------------------------------------------------
  3670                              <1> ; CHK_LASTRATE
  3671                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3672                              <1> ; ON ENTRY:
  3673                              <1> ;	DI = DRIVE #
  3674                              <1> ; ON EXIT:
  3675                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3676                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3677                              <1> ; REGISTERS ALTERED: DX
  3678                              <1> ;-------------------------------------------------------------------------------
  3679                              <1> CHK_LASTRATE:
  3680                              <1> 	;PUSH	AX			; SAVE REG.
  3681                              <1> 	; 24/12/2021
  3682 00001EF8 50                  <1> 	push	eax
  3683 00001EF9 2225[746B0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3684 00001EFF 8A87[796B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3685 00001F05 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3686 00001F09 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3687                              <1> 					; ZF = 1 RATE IS THE SAME
  3688                              <1> 	;POP	AX			; RESTORE REG.
  3689                              <1> 	; 24/12/2021
  3690 00001F0B 58                  <1> 	pop	eax
  3691 00001F0C C3                  <1> 	RETn
  3692                              <1> 
  3693                              <1> ;-------------------------------------------------------------------------------
  3694                              <1> ; DMA_SETUP
  3695                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3696                              <1> ;
  3697                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3698                              <1> ;
  3699                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3700                              <1> ;-------------------------------------------------------------------------------
  3701                              <1> 
  3702                              <1> ; SI = Head #, # of Sectors or DASD Type
  3703                              <1> 
  3704                              <1> ; 22/08/2015
  3705                              <1> ; 08/02/2015 - Protected Mode Modification
  3706                              <1> ; 06/02/2015 - 07/02/2015
  3707                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3708                              <1> ; (DMA Addres = Physical Address)
  3709                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3710                              <1> ;
  3711                              <1> ; 04/02/2016 (clc)
  3712                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3713                              <1> ; 16/12/2014 (IODELAY)
  3714                              <1> 
  3715                              <1> DMA_SETUP:
  3716                              <1> 
  3717                              <1> ;; 20/02/2015
  3718 00001F0D 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3719 00001F10 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3720 00001F16 7569                <1> 	jnz	short dma_bnd_err_stc
  3721                              <1> 	;
  3722                              <1> 	;push	ax			; DMA command
  3723                              <1> 	; 24/12/2021
  3724 00001F18 50                  <1> 	push	eax
  3725 00001F19 52                  <1> 	push	edx			; *
  3726 00001F1A B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3727 00001F1C E840030000          <1> 	call	GET_PARM		; 
  3728 00001F21 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3729                              <1> 	;mov	ax, si			; Sector count
  3730                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3731                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3732                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3733                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3734                              <1> 	; 24/12/2021
  3735 00001F23 89F2                <1> 	mov	edx, esi
  3736 00001F25 29C0                <1> 	sub	eax, eax
  3737 00001F27 88D4                <1> 	mov	ah, dl
  3738 00001F29 D1E8                <1> 	shr	eax, 1
  3739 00001F2B D3E0                <1> 	shl	eax, cl
  3740                              <1> 	;
  3741 00001F2D 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3742 00001F2F 6689C1              <1> 	mov	cx, ax
  3743 00001F32 5A                  <1> 	pop	edx			; *
  3744                              <1> 	;pop	ax
  3745                              <1> 	; 24/12/2021
  3746 00001F33 58                  <1> 	pop	eax
  3747 00001F34 3C42                <1> 	cmp	al, 42h
  3748 00001F36 7507                <1>         jne     short NOT_VERF
  3749 00001F38 BA0000FF00          <1> 	mov	edx, 0FF0000h
  3750 00001F3D EB08                <1> 	jmp	short J33
  3751                              <1> NOT_VERF:
  3752 00001F3F 6601CA              <1> 	add	dx, cx			; check for overflow
  3753 00001F42 723E                <1> 	jc	short dma_bnd_err
  3754                              <1> 	;
  3755 00001F44 6629CA              <1> 	sub	dx, cx			; Restore start address
  3756                              <1> J33:
  3757 00001F47 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3758 00001F48 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3759                              <1> 	IODELAY				; WAIT FOR I/O
  2101 00001F4A EB00                <2>  jmp short $+2
  2102 00001F4C EB00                <2>  jmp short $+2
  3760 00001F4E E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3761 00001F50 89D0                <1> 	mov	eax,edx			; Buffer address
  3762 00001F52 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3763                              <1> 	IODELAY				; WAIT FOR I/O
  2101 00001F54 EB00                <2>  jmp short $+2
  2102 00001F56 EB00                <2>  jmp short $+2
  3764 00001F58 88E0                <1> 	MOV	AL,AH
  3765 00001F5A E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3766 00001F5C C1E810              <1> 	shr	eax,16
  3767                              <1> 	IODELAY				; I/O WAIT STATE
  2101 00001F5F EB00                <2>  jmp short $+2
  2102 00001F61 EB00                <2>  jmp short $+2
  3768 00001F63 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3769                              <1> 	IODELAY
  2101 00001F65 EB00                <2>  jmp short $+2
  2102 00001F67 EB00                <2>  jmp short $+2
  3770 00001F69 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3771 00001F6C E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3772                              <1> 	IODELAY				; WAIT FOR I/O
  2101 00001F6E EB00                <2>  jmp short $+2
  2102 00001F70 EB00                <2>  jmp short $+2
  3773 00001F72 88E0                <1> 	MOV	AL,AH
  3774 00001F74 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3775                              <1> 	IODELAY
  2101 00001F76 EB00                <2>  jmp short $+2
  2102 00001F78 EB00                <2>  jmp short $+2
  3776 00001F7A FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3777 00001F7B B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3778 00001F7D E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3779                              <1> 
  3780 00001F7F F8                  <1> 	clc	; 04/02/2016
  3781 00001F80 C3                  <1> 	retn
  3782                              <1> 
  3783                              <1> dma_bnd_err_stc:
  3784 00001F81 F9                  <1> 	stc
  3785                              <1> dma_bnd_err:
  3786 00001F82 C605[6C6B0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3787 00001F89 C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3788                              <1> 
  3789                              <1> ;; 16/12/2014
  3790                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3791                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3792                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3793                              <1> ;;	IODELAY
  3794                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3795                              <1> ;;	;SIODELAY
  3796                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3797                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3798                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3799                              <1> ;;      ;JMP	SHORT J33
  3800                              <1> ;;;NOT_VERF:	
  3801                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3802                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3803                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3804                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3805                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3806                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3807                              <1> ;;	;JNC	short J33
  3808                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3809                              <1> ;;;J33:
  3810                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3811                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3812                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3813                              <1> ;;	IODELAY
  3814                              <1> ;;	MOV	AL,AH
  3815                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3816                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3817                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3818                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3819                              <1> ;;	IODELAY
  3820                              <1> ;;	;AND	AL,00001111B
  3821                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3822                              <1> ;;	;SIODELAY
  3823                              <1> ;;
  3824                              <1> ;;;----- DETERMINE COUNT
  3825                              <1> ;;	sub	eax, eax ; 08/02/2015
  3826                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3827                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3828                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3829                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3830                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3831                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3832                              <1> ;;	CALL	GET_PARM		; "
  3833                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3834                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3835                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3836                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3837                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3838                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3839                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3840                              <1> ;;	IODELAY
  3841                              <1> ;;	MOV	AL, AH
  3842                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3843                              <1> ;;	;IODELAY
  3844                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3845                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3846                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3847                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3848                              <1> ;;	add	ecx, eax ; 08/02/2015
  3849                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3850                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3851                              <1> ;;	SIODELAY
  3852                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3853                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3854                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3855                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3856                              <1> ;;	jz	short NO_BAD
  3857                              <1> ;;dma_bnd_err:
  3858                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3859                              <1> ;;NO_BAD:
  3860                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3861                              <1> 
  3862                              <1> ;-------------------------------------------------------------------------------
  3863                              <1> ; FMTDMA_SET
  3864                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3865                              <1> ;
  3866                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3867                              <1> ;
  3868                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3869                              <1> ;-------------------------------------------------------------------------------
  3870                              <1> 
  3871                              <1> 	; 24/12/2021
  3872                              <1> FMTDMA_SET:
  3873                              <1> ;; 20/02/2015 modification	
  3874 00001F8A 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3875 00001F8D F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3876 00001F93 75EC                <1> 	jnz	short dma_bnd_err_stc
  3877                              <1> 	;
  3878                              <1> 	;push	dx			; *
  3879                              <1> 	; 24/12/2021
  3880 00001F95 52                  <1> 	push	edx
  3881 00001F96 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3882 00001F98 E8C4020000          <1> 	call	GET_PARM		; "
  3883                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3884                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3885                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3886                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3887                              <1> 	;mov	cx, ax
  3888                              <1> 	; 24/12/2021
  3889 00001F9D 29C9                <1> 	sub	ecx, ecx
  3890 00001F9F 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3891 00001FA1 D1E1                <1> 	shl	ecx, 1
  3892 00001FA3 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3893 00001FA5 6649                <1> 	dec	cx
  3894                              <1> 	;pop	dx			; *
  3895                              <1> 	; 24/12/2021
  3896 00001FA7 5A                  <1> 	pop	edx
  3897 00001FA8 6601CA              <1> 	add	dx, cx			; check for overflow
  3898 00001FAB 72D5                <1> 	jc	short dma_bnd_err
  3899                              <1> 	;
  3900 00001FAD 6629CA              <1> 	sub	dx, cx			; Restore start address
  3901                              <1> 	;
  3902 00001FB0 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3903 00001FB2 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3904 00001FB3 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3905                              <1> 	IODELAY				; WAIT FOR I/O
  2101 00001FB5 EB00                <2>  jmp short $+2
  2102 00001FB7 EB00                <2>  jmp short $+2
  3906 00001FB9 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3907 00001FBB 89D0                <1> 	mov	eax,edx			; Buffer address
  3908 00001FBD E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3909                              <1> 	IODELAY				; WAIT FOR I/O
  2101 00001FBF EB00                <2>  jmp short $+2
  2102 00001FC1 EB00                <2>  jmp short $+2
  3910 00001FC3 88E0                <1> 	MOV	AL,AH
  3911 00001FC5 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3912 00001FC7 C1E810              <1> 	shr	eax,16
  3913                              <1> 	IODELAY				; I/O WAIT STATE
  2101 00001FCA EB00                <2>  jmp short $+2
  2102 00001FCC EB00                <2>  jmp short $+2
  3914 00001FCE E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3915                              <1> 	IODELAY
  2101 00001FD0 EB00                <2>  jmp short $+2
  2102 00001FD2 EB00                <2>  jmp short $+2
  3916 00001FD4 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3917 00001FD7 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3918                              <1> 	IODELAY				; WAIT FOR I/O
  2101 00001FD9 EB00                <2>  jmp short $+2
  2102 00001FDB EB00                <2>  jmp short $+2
  3919 00001FDD 88E0                <1> 	MOV	AL,AH
  3920 00001FDF E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3921                              <1> 	IODELAY
  2101 00001FE1 EB00                <2>  jmp short $+2
  2102 00001FE3 EB00                <2>  jmp short $+2
  3922 00001FE5 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3923 00001FE6 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3924 00001FE8 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3925 00001FEA C3                  <1> 	retn
  3926                              <1> 
  3927                              <1> ;; 08/02/2015 - Protected Mode Modification
  3928                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3929                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3930                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3931                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3932                              <1> ;;	IODELAY
  3933                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3934                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3935                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3936                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3937                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3938                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3939                              <1> ;;	;JNC	short J33A
  3940                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3941                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3942                              <1> ;;;J33A:
  3943                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3944                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3945                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3946                              <1> ;;	IODELAY
  3947                              <1> ;;	MOV	AL,AH
  3948                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3949                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3950                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3951                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3952                              <1> ;;	IODELAY
  3953                              <1> ;;	;AND	AL,00001111B
  3954                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3955                              <1> ;;
  3956                              <1> ;;;----- DETERMINE COUNT
  3957                              <1> ;;	sub	eax, eax ; 08/02/2015
  3958                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3959                              <1> ;;	CALL	GET_PARM		; "
  3960                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3961                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3962                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3963                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3964                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3965                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3966                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3967                              <1> ;;	IODELAY
  3968                              <1> ;;	MOV	AL, AH
  3969                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3970                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3971                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  3972                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  3973                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3974                              <1> ;;	add	ecx, eax ; 08/02/2015
  3975                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3976                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3977                              <1> ;;	SIODELAY
  3978                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3979                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  3980                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  3981                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  3982                              <1> ;;	jz	short FMTDMA_OK
  3983                              <1> ;;	stc	; 20/02/2015
  3984                              <1> ;;fmtdma_bnd_err:
  3985                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3986                              <1> ;;FMTDMA_OK:
  3987                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3988                              <1> 
  3989                              <1> ;-------------------------------------------------------------------------------
  3990                              <1> ; NEC_INIT	
  3991                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3992                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3993                              <1> ;
  3994                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3995                              <1> ;
  3996                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3997                              <1> ;-------------------------------------------------------------------------------
  3998                              <1> NEC_INIT:
  3999                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4000                              <1> 	; 24/12/2021
  4001 00001FEB 50                  <1> 	push	eax
  4002 00001FEC E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4003                              <1> 
  4004                              <1> ;-----	DO THE SEEK OPERATION
  4005                              <1> 
  4006 00001FF1 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4007 00001FF4 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4008                              <1> 	;POP	AX			; RECOVER COMMAND
  4009                              <1> 	; 24/12/2021
  4010 00001FF9 58                  <1> 	pop	eax
  4011 00001FFA 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4012 00001FFC BB[1A200000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4013 00002001 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4014                              <1> 
  4015                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4016                              <1> 
  4017 00002002 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4018 00002007 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4019 0000200A 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4020 0000200C C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4021 0000200F 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4022 00002012 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4023 00002014 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4024 00002019 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4025                              <1> ER_1:
  4026 0000201A C3                  <1> 	RETn
  4027                              <1> 
  4028                              <1> ;-------------------------------------------------------------------------------
  4029                              <1> ; RWV_COM
  4030                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4031                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4032                              <1> ;
  4033                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4034                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4035                              <1> ;-------------------------------------------------------------------------------
  4036                              <1> RWV_COM:
  4037 0000201B B8[66200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4038 00002020 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4039 00002021 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4040 00002024 E83E030000          <1> 	CALL	NEC_OUTPUT
  4041 00002029 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4042 0000202C E836030000          <1> 	CALL	NEC_OUTPUT
  4043 00002031 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4044 00002034 E82E030000          <1> 	CALL	NEC_OUTPUT
  4045 00002039 B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4046 0000203B E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4047 00002040 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4048 00002045 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4049 00002047 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4050 0000204C E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4051 00002051 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4052                              <1> _R15:
  4053 00002054 E80E030000          <1> 	CALL	NEC_OUTPUT
  4054 00002059 B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4055 0000205B E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4056 00002060 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4057 00002065 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4058                              <1> ER_2:
  4059 00002066 C3                  <1> 	RETn
  4060                              <1> 
  4061                              <1> ;-------------------------------------------------------------------------------
  4062                              <1> ; NEC_TERM
  4063                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4064                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4065                              <1> ;
  4066                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4067                              <1> ;-------------------------------------------------------------------------------
  4068                              <1> NEC_TERM:
  4069                              <1> 
  4070                              <1> ;-----	LET THE OPERATION HAPPEN
  4071                              <1> 
  4072 00002067 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4073 00002068 E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4074 0000206D 9C                  <1> 	PUSHFd	; 24/12/2021
  4075 0000206E E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4076 00002073 724B                <1> 	JC	short SET_END_POP
  4077 00002075 9D                  <1> 	POPFd	; 24/12/2021
  4078 00002076 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4079                              <1> 
  4080                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4081                              <1> 
  4082 00002078 FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4083 00002079 BE[6D6B0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4084 0000207E AC                  <1> 	lodsb				; GET ST0
  4085 0000207F 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4086 00002081 7433                <1> 	JZ	short SET_END
  4087 00002083 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4088 00002085 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4089                              <1> 
  4090                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4091                              <1> 
  4092 00002087 AC                  <1> 	lodsb				; GET ST1
  4093 00002088 D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4094 0000208A B404                <1> 	MOV	AH,RECORD_NOT_FND
  4095 0000208C 7222                <1> 	JC	short J19
  4096 0000208E C0E002              <1> 	SAL	AL,2
  4097 00002091 B410                <1> 	MOV	AH,BAD_CRC
  4098 00002093 721B                <1> 	JC	short J19
  4099 00002095 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4100 00002097 B408                <1> 	MOV	AH,BAD_DMA
  4101 00002099 7215                <1> 	JC	short J19
  4102 0000209B C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4103 0000209E B404                <1> 	MOV	AH,RECORD_NOT_FND
  4104 000020A0 720E                <1> 	JC	short J19
  4105 000020A2 D0E0                <1> 	SAL	AL,1
  4106 000020A4 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4107 000020A6 7208                <1> 	JC	short J19
  4108 000020A8 D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4109 000020AA B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4110 000020AC 7202                <1> 	JC	short J19
  4111                              <1> 
  4112                              <1> ;----- 	NEC MUST HAVE FAILED
  4113                              <1> J18:
  4114 000020AE B420                <1> 	MOV	AH,BAD_NEC
  4115                              <1> J19:
  4116 000020B0 0825[6C6B0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4117                              <1> SET_END:
  4118 000020B6 803D[6C6B0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4119 000020BD F5                  <1> 	CMC
  4120 000020BE 5E                  <1> 	POP	eSI
  4121 000020BF C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4122                              <1> 
  4123                              <1> SET_END_POP:
  4124 000020C0 9D                  <1> 	POPFd	; 24/12/2021
  4125 000020C1 EBF3                <1> 	JMP	SHORT SET_END
  4126                              <1> 
  4127                              <1> ;-------------------------------------------------------------------------------
  4128                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4129                              <1> ;-------------------------------------------------------------------------------
  4130                              <1> DSTATE:
  4131 000020C3 803D[6C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4132 000020CA 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4133 000020CC 808F[796B0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4134 000020D3 F687[796B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4135 000020DA 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4136 000020DC 8A87[796B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4137 000020E2 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4138 000020E4 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4139 000020E6 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4140                              <1> 
  4141                              <1> ;----- 	CHECK IF IT IS 1.44M
  4142                              <1> 
  4143 000020E8 E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4144                              <1> 	;;20/02/2015
  4145                              <1> 	;;JC	short M_12		; CMOS BAD
  4146 000020ED 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4147 000020EF 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4148 000020F1 7410                <1> 	JE	short M_12		; YES
  4149                              <1> M_720:
  4150 000020F3 80A7[796B0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4151 000020FA 808F[796B0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4152 00002101 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4153                              <1> M_12:	
  4154 00002103 808F[796B0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4155                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4156                              <1> SETBAC:
  4157 0000210A C3                  <1> 	RETn
  4158                              <1> 
  4159                              <1> ;-------------------------------------------------------------------------------
  4160                              <1> ; RETRY	
  4161                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4162                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4163                              <1> ;
  4164                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4165                              <1> ;-------------------------------------------------------------------------------
  4166                              <1> RETRY:
  4167 0000210B 803D[6C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4168 00002112 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4169 00002114 803D[6C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4170 0000211B 743C                <1> 	JZ	short NO_RETRY
  4171 0000211D 8AA7[796B0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4172 00002123 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4173 00002126 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4174 00002128 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4175 0000212B 8A2D[746B0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4176 00002131 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4177 00002134 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4178 00002137 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4179 00002139 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4180                              <1> 
  4181                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4182                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4183                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4184                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4185                              <1> 
  4186 0000213B 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4187 0000213E D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4188 00002140 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4189 00002143 80A7[796B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4190                              <1> 					; RATE, DBL STEP OFF
  4191 0000214A 08A7[796B0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4192 00002150 C605[6C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4193 00002157 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4194 00002158 C3                  <1> 	RETn				; RETRY RETURN
  4195                              <1> 
  4196                              <1> NO_RETRY:
  4197 00002159 F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4198 0000215A C3                  <1> 	RETn				; NO RETRY RETURN
  4199                              <1> 
  4200                              <1> ;-------------------------------------------------------------------------------
  4201                              <1> ; NUM_TRANS
  4202                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4203                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4204                              <1> ;
  4205                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4206                              <1> ;		SI-HI  = HEAD
  4207                              <1> ;		[BP]   = START SECTOR
  4208                              <1> ;
  4209                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4210                              <1> ;-------------------------------------------------------------------------------
  4211                              <1> NUM_TRANS:
  4212 0000215B 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4213 0000215D 803D[6C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4214                              <1> 	; 24/12/2021
  4215 00002164 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4216 00002166 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4217 00002168 E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4218 0000216D 8A1D[726B0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4219 00002173 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4220 00002176 3A2D[716B0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4221 0000217C 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4222 0000217E 8A2D[706B0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4223 00002184 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4224 00002187 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4225 00002189 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4226                              <1> DIF_HD:
  4227 0000218B 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4228                              <1> SAME_TRK:
  4229 0000218D 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4230 00002190 88D8                <1> 	MOV	AL,BL			; TO AL
  4231                              <1> NT_OUT:
  4232 00002192 C3                  <1> 	RETn
  4233                              <1> 
  4234                              <1> ;-------------------------------------------------------------------------------
  4235                              <1> ; SETUP_END
  4236                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4237                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4238                              <1> ;
  4239                              <1> ; ON EXIT:
  4240                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4241                              <1> ;-------------------------------------------------------------------------------
  4242                              <1> SETUP_END:
  4243 00002193 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4244                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4245 00002195 50                  <1> 	push	eax ; 24/12/2021
  4246 00002196 E8C6000000          <1> 	CALL	GET_PARM
  4247 0000219B 8825[6B6B0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4248                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4249 000021A1 58                  <1> 	pop	eax ; 24/12/2021
  4250 000021A2 8A25[6C6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4251 000021A8 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4252 000021AA 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4253 000021AC 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4254                              <1> NUN_ERR: 
  4255 000021AE 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4256 000021B1 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4257 000021B2 C3                  <1> 	RETn
  4258                              <1> 
  4259                              <1> ;-------------------------------------------------------------------------------
  4260                              <1> ; SETUP_DBL
  4261                              <1> ;	CHECK DOUBLE STEP.
  4262                              <1> ;
  4263                              <1> ; ON ENTRY :	DI = DRIVE
  4264                              <1> ;
  4265                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4266                              <1> ;-------------------------------------------------------------------------------
  4267                              <1> SETUP_DBL:
  4268 000021B3 8AA7[796B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4269 000021B9 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4270 000021BC 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4271                              <1> 
  4272                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4273                              <1> 
  4274 000021BE C605[696B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4275 000021C5 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4276 000021CA B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4277 000021CC E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4278 000021D1 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4279 000021D6 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4280                              <1> 
  4281                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4282                              <1> 
  4283 000021D8 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4284 000021DC F687[796B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4285 000021E3 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4286 000021E5 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4287                              <1> 
  4288                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4289                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4290                              <1> ;	THEN SET DOUBLE STEP ON.
  4291                              <1> 
  4292                              <1> CNT_OK:
  4293 000021E7 C605[6B6B0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4294                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4295                              <1> 	; 24/12/2021
  4296 000021EE 51                  <1> 	push	ecx
  4297 000021EF C605[6C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4298 000021F6 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4299 000021F9 D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4300 000021FB C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4301                              <1> 	;PUSH	AX			; SAVE HEAD
  4302                              <1> 	; 24/12/2021
  4303 000021FE 50                  <1> 	push	eax
  4304 000021FF E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4305                              <1> 	;POP	AX			; RESTORE HEAD
  4306                              <1> 	; 24/12/2021
  4307 00002204 58                  <1> 	pop	eax
  4308 00002205 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4309 00002208 E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4310 0000220D 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4311 0000220E 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4312 00002213 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4313                              <1> 	;POP	CX			; RESTORE COUNT
  4314                              <1> 	; 24/12/2021
  4315 00002214 59                  <1> 	pop	ecx
  4316 00002215 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4317 00002217 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4318 00002219 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4319 0000221B 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4320                              <1> 
  4321                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4322                              <1> 
  4323                              <1> SD_ERR:	
  4324 0000221D F9                  <1> 	STC				; SET CARRY FOR ERROR
  4325 0000221E C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4326                              <1> 
  4327                              <1> DO_CHK:
  4328 0000221F 8A0D[706B0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4329 00002225 888F[7D6B0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4330 0000222B D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4331 0000222D 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4332 0000222F 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4333 00002231 808F[796B0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4334                              <1> NO_DBL:
  4335 00002238 F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4336 00002239 C3                  <1> 	RETn
  4337                              <1> 
  4338                              <1> ;-------------------------------------------------------------------------------
  4339                              <1> ; READ_ID
  4340                              <1> ;	READ ID FUNCTION.
  4341                              <1> ;
  4342                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4343                              <1> ;
  4344                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4345                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4346                              <1> ;-------------------------------------------------------------------------------
  4347                              <1> READ_ID:
  4348 0000223A B8[57220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4349 0000223F 50                  <1> 	PUSH	eAX
  4350 00002240 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4351 00002242 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4352 00002247 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4353 0000224A 88C4                <1> 	MOV	AH,AL
  4354 0000224C E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4355 00002251 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4356 00002256 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4357                              <1> ER_3:
  4358 00002257 C3                  <1> 	RETn
  4359                              <1> 
  4360                              <1> ;-------------------------------------------------------------------------------
  4361                              <1> ; CMOS_TYPE
  4362                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4363                              <1> ;
  4364                              <1> ; ON ENTRY:	DI = DRIVE #
  4365                              <1> ;
  4366                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4367                              <1> ;-------------------------------------------------------------------------------
  4368                              <1> 
  4369                              <1> CMOS_TYPE: ; 11/12/2014
  4370 00002258 8A87[DE650000]      <1> 	mov	al, [eDI+fd0_type]
  4371 0000225E 20C0                <1> 	and 	al, al ; 18/12/2014
  4372 00002260 C3                  <1> 	retn
  4373                              <1> 
  4374                              <1> ;CMOS_TYPE:
  4375                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4376                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4377                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4378                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4379                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4380                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4381                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4382                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4383                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4384                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4385                              <1> ;TB:
  4386                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4387                              <1> ;BAD_CM:
  4388                              <1> ;	RETn				; CY, STATUS OF READ
  4389                              <1> 
  4390                              <1> ;-------------------------------------------------------------------------------
  4391                              <1> ; GET_PARM
  4392                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4393                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4394                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4395                              <1> ;	THE PARAMETER IN DL.
  4396                              <1> ;
  4397                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4398                              <1> ;
  4399                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4400                              <1> ;		AL,DH DESTROYED
  4401                              <1> ;-------------------------------------------------------------------------------
  4402                              <1> GET_PARM:
  4403                              <1> 	;PUSH	DS
  4404 00002261 56                  <1> 	PUSH	eSI
  4405                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4406                              <1>     	;MOV	DS,AX
  4407                              <1> 	;;mov	ax, cs
  4408                              <1> 	;;mov	ds, ax
  4409                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4410 00002262 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4411                              <1> 	;SUB	BH,BH			; BX = INDEX
  4412 00002264 81E3FF000000        <1> 	and	ebx, 0FFh
  4413                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4414                              <1> 	;
  4415                              <1> 	; 17/12/2014
  4416 0000226A 66A1[D1650000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4417 00002270 38E0                <1> 	cmp	al, ah
  4418 00002272 7425                <1> 	je	short gpndc
  4419 00002274 A2[D2650000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4420 00002279 53                  <1> 	push	ebx ; 08/02/2015
  4421 0000227A 88C3                <1> 	mov	bl, al 
  4422                              <1> 	; 11/12/2014
  4423 0000227C 8A83[DE650000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4424                              <1> 	; 18/12/2014
  4425 00002282 20C0                <1> 	and	al, al
  4426 00002284 7507                <1> 	jnz	short gpdtc
  4427 00002286 BB[BB650000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4428 0000228B EB05                <1>         jmp     short gpdpu
  4429                              <1> gpdtc:	
  4430 0000228D E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4431                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4432                              <1> gpdpu:
  4433 00002292 891D[58650000]      <1> 	mov	[DISK_POINTER], ebx
  4434 00002298 5B                  <1> 	pop	ebx
  4435                              <1> gpndc:
  4436 00002299 8B35[58650000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4437 0000229F 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4438 000022A2 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4439 000022A4 5E                  <1> 	POP	eSI
  4440                              <1> 	;POP	DS
  4441 000022A5 C3                  <1> 	RETn
  4442                              <1> 
  4443                              <1> ;-------------------------------------------------------------------------------
  4444                              <1> ; MOTOR_ON
  4445                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4446                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4447                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4448                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4449                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4450                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4451                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4452                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4453                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4454                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4455                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4456                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4457                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4458                              <1> ;
  4459                              <1> ; ON ENTRY:	DI = DRIVE #
  4460                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4461                              <1> ;-------------------------------------------------------------------------------
  4462                              <1> MOTOR_ON:
  4463 000022A6 53                  <1> 	PUSH	eBX			; SAVE REG.
  4464 000022A7 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4465 000022AC 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4466 000022AE E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4467 000022B3 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4468                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4469                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4470                              <1> M_WAIT:
  4471 000022B8 B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4472 000022BA E8A2FFFFFF          <1> 	CALL	GET_PARM
  4473                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4474                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4475                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4476 000022BF 80FC08              <1> 	cmp	ah, 8
  4477                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4478 000022C2 7702                <1> 	ja	short J13
  4479                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4480 000022C4 B408                <1> 	mov	ah, 8
  4481                              <1> 
  4482                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4483                              <1> GP2:	
  4484                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4485                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4486 000022C6 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4487 000022CB E806F2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4488                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4489 000022D0 FECC                <1> 	dec	ah
  4490 000022D2 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4491                              <1> MOT_IS_ON:
  4492 000022D4 5B                  <1> 	POP	eBX			; RESTORE REG.
  4493 000022D5 C3                  <1> 	RETn
  4494                              <1> 
  4495                              <1> ;-------------------------------------------------------------------------------
  4496                              <1> ; TURN_ON
  4497                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4498                              <1> ;
  4499                              <1> ; ON ENTRY:	DI = DRIVE #
  4500                              <1> ;
  4501                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4502                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4503                              <1> ;		AX,BX,CX,DX DESTROYED
  4504                              <1> ;-------------------------------------------------------------------------------
  4505                              <1> TURN_ON:
  4506 000022D6 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4507 000022D8 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4508 000022DA C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4509 000022DD FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4510 000022DE C605[6B6B0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4511 000022E5 A0[6A6B0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4512 000022EA 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4513 000022EC B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4514 000022EE D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4515                              <1> 
  4516                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4517                              <1> ;  BL = DRIVE SELECT DESIRED
  4518                              <1> ;  AH = MOTOR ON MASK DESIRED
  4519                              <1> 
  4520 000022F0 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4521 000022F2 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4522 000022F4 8425[6A6B0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4523 000022FA 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4524                              <1> 
  4525                              <1> TURN_IT_ON:
  4526 000022FC 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4527 000022FE 8A3D[6A6B0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4528 00002304 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4529 00002307 8025[6A6B0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4530 0000230E 0825[6A6B0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4531 00002314 A0[6A6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4532 00002319 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4533 0000231B 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4534 0000231E FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4535 0000231F 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4536 00002321 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4537 00002324 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4538 00002326 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4539 0000232A EE                  <1> 	OUT	DX,AL
  4540 0000232B 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4541                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4542 0000232D 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4543 0000232F F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4544 00002330 C3                  <1> 	RETn
  4545                              <1> 
  4546                              <1> NO_MOT_WAIT:
  4547 00002331 FB                  <1> 	sti
  4548                              <1> no_mot_w1: ; 27/02/2015
  4549 00002332 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4550                              <1> 	;STI				; INTERRUPTS BACK ON
  4551 00002333 C3                  <1> 	RETn
  4552                              <1> 
  4553                              <1> ;-------------------------------------------------------------------------------
  4554                              <1> ; HD_WAIT
  4555                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4556                              <1> ;
  4557                              <1> ; ON ENTRY:	DI = DRIVE #
  4558                              <1> ;
  4559                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4560                              <1> ;-------------------------------------------------------------------------------
  4561                              <1> HD_WAIT:
  4562 00002334 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4563 00002336 E826FFFFFF          <1> 	CALL	GET_PARM
  4564 0000233B 08E4                <1> 	or	ah, ah	; 17/12/2014
  4565 0000233D 7519                <1> 	jnz	short DO_WAT
  4566 0000233F F605[6A6B0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4567                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4568                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4569                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4570 00002346 741E                <1> 	jz	short HW_DONE
  4571 00002348 B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4572 0000234A 8A87[796B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4573 00002350 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4574 00002352 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4575 00002354 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4576                              <1> ;GP3:
  4577 00002356 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4578                              <1> ;	JMP	SHORT DO_WAT
  4579                              <1> 
  4580                              <1> ;ISNT_WRITE:
  4581                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4582                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4583                              <1> 
  4584                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4585                              <1> DO_WAT:
  4586                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4587                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4588                              <1> J29:					; 	1 MILLISECOND LOOP
  4589                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4590 00002358 B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4591 0000235D E874F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4592                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4593 00002362 FECC                <1> 	dec	ah
  4594 00002364 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4595                              <1> HW_DONE:
  4596 00002366 C3                  <1> 	RETn
  4597                              <1> 
  4598                              <1> ;-------------------------------------------------------------------------------
  4599                              <1> ; NEC_OUTPUT
  4600                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4601                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4602                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4603                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4604                              <1> ; 
  4605                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4606                              <1> ;
  4607                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4608                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4609                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4610                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4611                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4612                              <1> ;		AX,CX,DX DESTROYED
  4613                              <1> ;-------------------------------------------------------------------------------
  4614                              <1> 
  4615                              <1> ; 09/12/2014 [Erdogan Tan] 
  4616                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4617                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4618                              <1> ;	This read only register facilitates the transfer of data between
  4619                              <1> ;	the system microprocessor and the controller.
  4620                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4621                              <1> ;	  with the system micrprocessor.
  4622                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4623                              <1> ;	  the transfer is to the controller.
  4624                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4625                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4626                              <1> ; Bit 3 - Reserved.
  4627                              <1> ; Bit 2 - Reserved.
  4628                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4629                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4630                              <1> 
  4631                              <1> ; Data Register (3F5h)
  4632                              <1> ; This read/write register passes data, commands and parameters, and provides
  4633                              <1> ; diskette status information.
  4634                              <1>   		
  4635                              <1> NEC_OUTPUT:
  4636                              <1> 	;PUSH	BX			; SAVE REG.
  4637 00002367 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4638                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4639                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4640                              <1> 	; 16/12/2014
  4641                              <1> 	; waiting for (max.) 0.5 seconds
  4642                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4643                              <1> 	;
  4644                              <1> 	; 17/12/2014
  4645                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4646                              <1> 	;
  4647                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4648                              <1> 	;		go on.
  4649                              <1> 	;INPUT:
  4650                              <1> 	;	AH=Mask for isolation bits.
  4651                              <1> 	;	AL=pattern to look for.
  4652                              <1> 	;	DX=Port to test for
  4653                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4654                              <1> 	;	     (normally 30 microseconds per period.)
  4655                              <1> 	;
  4656                              <1> 	;WFP_SHORT:  
  4657                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4658                              <1> 	;
  4659                              <1> 
  4660                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4661                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4662 0000236B B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4663                              <1> ;
  4664                              <1> ;WFPS_OUTER_LP:
  4665                              <1> ;	;
  4666                              <1> ;WFPS_CHECK_PORT:
  4667                              <1> J23:
  4668 00002370 EC                  <1> 	IN	AL,DX			; GET STATUS
  4669 00002371 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4670 00002373 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4671 00002375 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4672                              <1> WFPS_HI:
  4673 00002377 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4674 00002379 A810                <1> 	TEST	AL,010H			; transition on memory
  4675 0000237B 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4676                              <1> WFPS_LO:
  4677 0000237D E461                <1> 	IN	AL, PORT_B		; SYS1
  4678 0000237F A810                <1> 	TEST	AL,010H
  4679 00002381 74FA                <1> 	JZ	SHORT WFPS_LO
  4680                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4681 00002383 E2EB                <1> 	loop	J23	; 27/02/2015
  4682                              <1> ;	;
  4683                              <1> ;	dec	bl
  4684                              <1> ;	jnz	short WFPS_OUTER_LP
  4685                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4686                              <1> ;J23:
  4687                              <1> ;	IN	AL,DX			; GET STATUS
  4688                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4689                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4690                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4691                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4692                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4693                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4694                              <1>    
  4695                              <1> 	;;27/02/2015
  4696                              <1> 	;16/12/2014
  4697                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4698                              <1> 	;;jb	short J23
  4699                              <1> 
  4700                              <1> ;WFPS_TIMEOUT:
  4701                              <1> 
  4702                              <1> ;-----	FALL THRU TO ERROR RETURN
  4703                              <1> 
  4704 00002385 800D[6C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4705                              <1> 	;POP	BX			; RESTORE REG.
  4706 0000238C 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4707 0000238D F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4708 0000238E C3                  <1> 	RETn
  4709                              <1> 
  4710                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4711                              <1> 
  4712                              <1> J27:	
  4713 0000238F 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4714 00002391 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4715 00002393 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4716                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4717                              <1> 	; 27/02/2015
  4718 00002394 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4719                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4720 00002395 29C9                <1> 	sub	ecx, ecx
  4721 00002397 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4722 00002399 E838F1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4723 0000239E 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4724                              <1> 	;POP	BX			; RESTORE REG
  4725 0000239F C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4726                              <1> 
  4727                              <1> ;-------------------------------------------------------------------------------
  4728                              <1> ; SEEK
  4729                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4730                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4731                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4732                              <1> ;
  4733                              <1> ; ON ENTRY:	DI = DRIVE #
  4734                              <1> ;		CH = TRACK #
  4735                              <1> ;
  4736                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4737                              <1> ;		AX,BX,CX DX DESTROYED
  4738                              <1> ;-------------------------------------------------------------------------------
  4739                              <1> SEEK:
  4740 000023A0 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4741 000023A2 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4742 000023A4 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4743 000023A6 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4744 000023A8 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4745 000023AA 8405[696B0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4746 000023B0 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4747                              <1> 
  4748 000023B2 0805[696B0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4749 000023B8 E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4750 000023BD 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4751                              <1> 
  4752                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4753                              <1> 
  4754 000023BF C605[6C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4755 000023C6 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4756 000023CB 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4757                              <1> 
  4758                              <1> AFT_RECAL:
  4759 000023CD C687[7D6B0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4760 000023D4 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4761 000023D6 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4762                              <1> 
  4763                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4764                              <1> 
  4765 000023D8 F687[796B0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4766 000023DF 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4767 000023E1 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4768                              <1> 
  4769 000023E3 3AAF[7D6B0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4770 000023E9 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4771                              <1> 
  4772 000023EB BA[1E240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4773 000023F0 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4774 000023F1 88AF[7D6B0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4775 000023F7 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4776 000023F9 E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4777 000023FE 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4778 00002400 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4779 00002402 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4780 00002407 8AA7[7D6B0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4781 0000240D E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4782 00002412 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4783                              <1> 
  4784                              <1> ;-----	WAIT FOR HEAD SETTLE
  4785                              <1> 
  4786                              <1> DO_WAIT:
  4787 00002417 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4788 00002418 E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4789 0000241D 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4790                              <1> RB:
  4791                              <1> NEC_ERR:
  4792                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4793                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4794 0000241E C3                  <1> 	RETn				; RETURN TO CALLER
  4795                              <1> 
  4796                              <1> ;-------------------------------------------------------------------------------
  4797                              <1> ; RECAL
  4798                              <1> ;	RECALIBRATE DRIVE
  4799                              <1> ;
  4800                              <1> ; ON ENTRY:	DI = DRIVE #
  4801                              <1> ;
  4802                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4803                              <1> ;-------------------------------------------------------------------------------
  4804                              <1> RECAL:
  4805                              <1> 	;PUSH	CX
  4806                              <1> 	; 24/12/2021
  4807 0000241F 51                  <1> 	push	ecx
  4808 00002420 B8[3C240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4809 00002425 50                  <1> 	PUSH	eAX
  4810 00002426 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4811 00002428 E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4812 0000242D 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4813 0000242F 88DC                <1> 	MOV	AH,BL
  4814 00002431 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4815 00002436 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4816 0000243B 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4817                              <1> RC_BACK:
  4818                              <1> 	;POP	CX
  4819                              <1> 	; 24/12/2021
  4820 0000243C 59                  <1> 	pop	ecx
  4821 0000243D C3                  <1> 	RETn
  4822                              <1> 
  4823                              <1> ;-------------------------------------------------------------------------------
  4824                              <1> ; CHK_STAT_2
  4825                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4826                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4827                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4828                              <1> ;
  4829                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4830                              <1> ;-------------------------------------------------------------------------------
  4831                              <1> CHK_STAT_2:
  4832 0000243E B8[66240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4833 00002443 50                  <1> 	PUSH	eAX
  4834 00002444 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4835 00002449 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4836 0000244B B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4837 0000244D E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4838 00002452 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4839 00002457 720C                <1> 	JC	short J34
  4840 00002459 A0[6D6B0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4841 0000245E 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4842 00002460 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4843 00002462 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4844 00002464 F8                  <1> 	CLC				; GOOD RETURN
  4845                              <1> J34:
  4846 00002465 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4847                              <1> CS_BACK:
  4848 00002466 C3                  <1> 	RETn
  4849                              <1> J35:
  4850 00002467 800D[6C6B0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4851 0000246E F9                  <1> 	STC				; ERROR RETURN CODE
  4852 0000246F EBF4                <1> 	JMP	SHORT J34
  4853                              <1> 
  4854                              <1> ;-------------------------------------------------------------------------------
  4855                              <1> ; WAIT_INT
  4856                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4857                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4858                              <1> ;	IF THE DRIVE IS NOT READY.
  4859                              <1> ;
  4860                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4861                              <1> ;-------------------------------------------------------------------------------
  4862                              <1> 
  4863                              <1> ; 17/12/2014
  4864                              <1> ; 2.5 seconds waiting !
  4865                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4866                              <1> ; amount of time to wait for completion interrupt from NEC.
  4867                              <1> 
  4868                              <1> 
  4869                              <1> WAIT_INT:
  4870 00002471 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4871 00002472 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4872                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4873                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4874                              <1> 
  4875                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4876                              <1> 	;
  4877                              <1> 	;WAIT_FOR_MEM:	
  4878                              <1> 	;	Waits for a bit at a specified memory location pointed
  4879                              <1> 	;	to by ES:[DI] to become set.
  4880                              <1> 	;INPUT:
  4881                              <1> 	;	AH=Mask to test with.
  4882                              <1> 	;	ES:[DI] = memory location to watch.
  4883                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4884                              <1> 	;	     (normally 30 microseconds per period.)
  4885                              <1> 
  4886                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4887                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4888                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4889                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4890                              <1> 	; 27/02/2015
  4891 00002473 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4892                              <1> WFMS_CHECK_MEM:
  4893 00002478 F605[696B0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4894 0000247F 7516                <1>         jnz     short J37
  4895                              <1> WFMS_HI:
  4896 00002481 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4897 00002483 A810                <1> 	TEST	AL,010H			; transition on memory
  4898 00002485 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4899                              <1> WFMS_LO:
  4900 00002487 E461                <1> 	IN	AL,PORT_B		;SYS1
  4901 00002489 A810                <1> 	TEST	AL,010H
  4902 0000248B 74FA                <1> 	JZ	SHORT WFMS_LO
  4903 0000248D E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4904                              <1> ;WFMS_OUTER_LP:
  4905                              <1> ;;	or	bl, bl			; check outer counter
  4906                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4907                              <1> ;	dec	bl
  4908                              <1> ;	jz	short J36A	
  4909                              <1> ;	jmp	short WFMS_CHECK_MEM
  4910                              <1> 
  4911                              <1> 	;17/12/2014
  4912                              <1> 	;16/12/2014
  4913                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4914                              <1> ;J36:
  4915                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4916                              <1> ;	JNZ	short J37
  4917                              <1> 	;16/12/2014
  4918                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4919                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4920                              <1> 	;JNZ	short J36
  4921                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4922                              <1> ;	jb	short J36
  4923                              <1> 
  4924                              <1> ;WFMS_TIMEOUT:
  4925                              <1> ;J36A:
  4926 0000248F 800D[6C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4927 00002496 F9                  <1> 	STC				; ERROR RETURN
  4928                              <1> J37:
  4929 00002497 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4930 00002498 8025[696B0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4931 0000249F 9D                  <1> 	POPF				; RECOVER CARRY
  4932 000024A0 C3                  <1> 	RETn				; GOOD RETURN CODE
  4933                              <1> 
  4934                              <1> ;-------------------------------------------------------------------------------
  4935                              <1> ; RESULTS
  4936                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4937                              <1> ;	FOLLOWING AN INTERRUPT.
  4938                              <1> ;
  4939                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4940                              <1> ;		AX,BX,CX,DX DESTROYED
  4941                              <1> ;-------------------------------------------------------------------------------
  4942                              <1> RESULTS:
  4943 000024A1 57                  <1> 	PUSH	eDI
  4944 000024A2 BF[6D6B0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4945 000024A7 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4946 000024A9 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4947                              <1> 
  4948                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4949                              <1> 
  4950                              <1> _R10: 
  4951                              <1> 	; 16/12/2014
  4952                              <1> 	; wait for (max) 0.5 seconds
  4953                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4954                              <1> 	;XOR	CX,CX			; COUNTER
  4955                              <1> 
  4956                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4957                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4958                              <1> 	; 27/02/2015
  4959 000024AD B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4960                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4961                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4962                              <1> 
  4963                              <1> WFPSR_OUTER_LP:
  4964                              <1> 	;
  4965                              <1> WFPSR_CHECK_PORT:
  4966                              <1> J39:					; WAIT FOR MASTER
  4967 000024B2 EC                  <1> 	IN	AL,DX			; GET STATUS
  4968 000024B3 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4969 000024B5 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4970 000024B7 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4971                              <1> WFPSR_HI:
  4972 000024B9 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4973 000024BB A810                <1> 	TEST	AL,010H			; transition on memory
  4974 000024BD 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  4975                              <1> WFPSR_LO:
  4976 000024BF E461                <1> 	IN	AL, PORT_B		; SYS1
  4977 000024C1 A810                <1> 	TEST	AL,010H
  4978 000024C3 74FA                <1> 	JZ	SHORT WFPSR_LO
  4979 000024C5 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  4980                              <1> 	;; 27/02/2015
  4981                              <1> 	;;dec	bh
  4982                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4983                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4984                              <1> 
  4985                              <1> 	;;mov	byte [wait_count], 0
  4986                              <1> ;J39:					; WAIT FOR MASTER
  4987                              <1> ;	IN	AL,DX			; GET STATUS
  4988                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4989                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4990                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  4991                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  4992                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  4993                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  4994                              <1> 	;
  4995                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  4996                              <1> 	;;jb	short J39	
  4997                              <1> 
  4998                              <1> ;WFPSR_TIMEOUT:
  4999 000024C7 800D[6C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5000 000024CE F9                  <1> 	STC				; SET ERROR RETURN
  5001 000024CF EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5002                              <1> 
  5003                              <1> ;-----	READ IN THE STATUS
  5004                              <1> 
  5005                              <1> J42:
  5006 000024D1 EB00                <1> 	JMP	$+2			; I/O DELAY
  5007 000024D3 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5008 000024D5 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5009                              <1> 	; 16/12/2014
  5010                              <1> 	NEWIODELAY
  2106 000024D6 E6EB                <2>  out 0EBh,al
  5011 000024D8 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5012 000024DA 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5013                              <1> 	; 16/12/2014
  5014                              <1> ;	push	cx
  5015                              <1> ;	mov	cx, 30
  5016                              <1> ;wdw2:
  5017                              <1> ;	NEWIODELAY
  5018                              <1> ;	loop	wdw2
  5019                              <1> ;	pop	cx
  5020                              <1> 
  5021 000024DB B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5022 000024E0 E8F1EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5023 000024E5 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5024 000024E7 EC                  <1> 	IN	AL,DX			; GET STATUS
  5025                              <1> 	; 16/12/2014
  5026                              <1> 	NEWIODELAY
  2106 000024E8 E6EB                <2>  out 0EBh,al
  5027                              <1> 	;
  5028 000024EA A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5029 000024EC 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5030                              <1> 
  5031 000024EE FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5032 000024F0 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5033 000024F2 800D[6C6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5034 000024F9 F9                  <1> 	STC				; SET ERROR FLAG
  5035                              <1> 
  5036                              <1> ;-----	RESULT OPERATION IS DONE
  5037                              <1> POPRES:
  5038 000024FA 5F                  <1> 	POP	eDI
  5039 000024FB C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5040                              <1> 
  5041                              <1> ;-------------------------------------------------------------------------------
  5042                              <1> ; READ_DSKCHNG
  5043                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5044                              <1> ;
  5045                              <1> ; ON ENTRY:	DI = DRIVE #
  5046                              <1> ;
  5047                              <1> ; ON EXIT:	DI = DRIVE #
  5048                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5049                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5050                              <1> ;		AX,CX,DX DESTROYED
  5051                              <1> ;-------------------------------------------------------------------------------
  5052                              <1> READ_DSKCHNG:
  5053 000024FC E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5054 00002501 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5055 00002505 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5056 00002506 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5057 00002508 C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5058                              <1> 
  5059                              <1> ;-------------------------------------------------------------------------------
  5060                              <1> ; DRIVE_DET
  5061                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5062                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5063                              <1> ; ON ENTRY:	DI = DRIVE #
  5064                              <1> ;-------------------------------------------------------------------------------
  5065                              <1> DRIVE_DET:
  5066 00002509 E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5067 0000250E E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5068 00002513 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5069 00002515 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5070 00002517 E884FEFFFF          <1> 	CALL	SEEK
  5071 0000251C 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5072 0000251E B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5073                              <1> SK_GIN:
  5074 00002520 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5075                              <1> 	;PUSH	CX			; SAVE TRACK
  5076                              <1> 	; 24/12/2021
  5077 00002522 51                  <1> 	push	ecx
  5078 00002523 E878FEFFFF          <1> 	CALL	SEEK
  5079 00002528 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5080 0000252A B8[65250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5081 0000252F 50                  <1> 	PUSH	eAX
  5082 00002530 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5083 00002532 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5084 00002537 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5085 0000253A 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5086 0000253C E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5087 00002541 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5088 00002546 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5089                              <1> 	;POP	CX			; RESTORE TRACK
  5090                              <1> 	; 24/12/2021
  5091 00002547 59                  <1> 	pop	ecx
  5092 00002548 F605[6D6B0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5093 0000254F 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5094 00002551 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5095 00002553 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5096                              <1> 
  5097                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5098                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5099                              <1> 
  5100 00002555 808F[796B0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5101 0000255C C3                  <1> 	RETn				; ALL INFORMATION SET
  5102                              <1> IS_80:
  5103 0000255D 808F[796B0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5104                              <1> DD_BAC:
  5105 00002564 C3                  <1> 	RETn
  5106                              <1> POP_BAC:
  5107                              <1> 	;POP	CX			; THROW AWAY
  5108                              <1> 	; 24/12/2021
  5109 00002565 59                  <1> 	pop	ecx
  5110 00002566 C3                  <1> 	RETn
  5111                              <1> 
  5112                              <1> fdc_int:  
  5113                              <1> 	  ; 30/07/2015	
  5114                              <1> 	  ; 16/02/2015
  5115                              <1> ;int_0Eh: ; 11/12/2014
  5116                              <1> 
  5117                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5118                              <1> ; DISK_INT
  5119                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5120                              <1> ;
  5121                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5122                              <1> ;-------------------------------------------------------------------------------
  5123                              <1> DISK_INT_1:
  5124                              <1> 
  5125                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5126                              <1> 	; 24/12/2021
  5127 00002567 50                  <1> 	push	eax
  5128 00002568 1E                  <1> 	push	ds
  5129 00002569 66B81000            <1> 	mov	ax, KDATA
  5130 0000256D 8ED8                <1> 	mov 	ds, ax
  5131 0000256F 800D[696B0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5132 00002576 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5133 00002578 E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5134 0000257A 1F                  <1> 	pop	ds
  5135                              <1> 	;POP	AX			; RECOVER REGISTER
  5136                              <1> 	; 24/12/2021
  5137 0000257B 58                  <1> 	pop	eax
  5138 0000257C CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5139                              <1> 
  5140                              <1> ;-------------------------------------------------------------------------------
  5141                              <1> ; DSKETTE_SETUP
  5142                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5143                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5144                              <1> ;-------------------------------------------------------------------------------
  5145                              <1> DSKETTE_SETUP:
  5146                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5147                              <1> 	;PUSH	BX
  5148                              <1> 	;PUSH	CX
  5149 0000257D 52                  <1> 	PUSH	eDX
  5150                              <1> 	;PUSH	DI
  5151                              <1> 	;;PUSH	DS
  5152                              <1> 	; 14/12/2014
  5153                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5154                              <1> 	;mov	[DISK_POINTER+2], cs
  5155                              <1> 	;
  5156                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5157 0000257E 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5158 00002580 66C705[796B0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5158 00002588 00                  <1>
  5159 00002589 8025[746B0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5160 00002590 800D[746B0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5161 00002597 C605[696B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5162 0000259E C605[6B6B0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5163 000025A5 C605[6A6B0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5164 000025AC C605[6C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5165                              <1> 	;
  5166                              <1> 	; 28/02/2015
  5167                              <1> 	;mov	word [cfd], 100h 
  5168 000025B3 E89DF2FFFF          <1> 	call	DSK_RESET
  5169 000025B8 5A                  <1> 	pop	edx
  5170 000025B9 C3                  <1> 	retn
  5171                              <1> 
  5172                              <1> ;SUP0:
  5173                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5174                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5175                              <1> ;	; 02/01/2015
  5176                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5177                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5178                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5179                              <1> ;       cmp     byte [fd1_type], 0	
  5180                              <1> ;	jna	short sup1
  5181                              <1> ;	or	di, di
  5182                              <1> ;	jnz	short sup1
  5183                              <1> ;	inc	di
  5184                              <1> ;       jmp     short SUP0
  5185                              <1> ;sup1:
  5186                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5187                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5188                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5189                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5190                              <1> ;	;POP	DI
  5191                              <1> ;	POP	eDX
  5192                              <1> ;	;POP	CX
  5193                              <1> ;	;POP	BX
  5194                              <1> ;	;POP	AX
  5195                              <1> ;	RETn
  5196                              <1> 
  5197                              <1> ;//////////////////////////////////////////////////////
  5198                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5199                              <1> ;
  5200                              <1> 
  5201                              <1> int13h: ; 21/02/2015
  5202 000025BA 9C                  <1> 	pushfd
  5203 000025BB 0E                  <1> 	push 	cs
  5204 000025BC E858000000          <1> 	call 	DISK_IO
  5205 000025C1 C3                  <1> 	retn
  5206                              <1> 
  5207                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5208                              <1> ;/////////////////////////////////////////////////////////////////////
  5209                              <1> 
  5210                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5211                              <1> ; 23/02/2015
  5212                              <1> ; 21/02/2015 (unix386.s)
  5213                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5214                              <1> ;
  5215                              <1> ; Original Source Code:
  5216                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5217                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5218                              <1> ;
  5219                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5220                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5221                              <1> ;
  5222                              <1> 
  5223                              <1> ;The wait for controller to be not busy is 10 seconds.
  5224                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5225                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5226                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5227                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5228                              <1> 
  5229                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5230                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5231                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5232                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5233                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5234                              <1> 
  5235                              <1> ;The wait for Data request on read and write longs is
  5236                              <1> ;2000 us. (?)
  5237                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5238                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5239                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5240                              <1> 
  5241                              <1> ; Port 61h (PORT_B)
  5242                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5243                              <1> 
  5244                              <1> ; 23/12/2014
  5245                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5246                              <1> 
  5247                              <1> ;--- INT 13H -------------------------------------------------------------------
  5248                              <1> ;									       :
  5249                              <1> ; FIXED DISK I/O INTERFACE						       :
  5250                              <1> ;									       :
  5251                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5252                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5253                              <1> ;									       :
  5254                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5255                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5256                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5257                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5258                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5259                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5260                              <1> ;									       :
  5261                              <1> ;------------------------------------------------------------------------------:
  5262                              <1> ;									       :
  5263                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5264                              <1> ;									       :
  5265                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5266                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5267                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5268                              <1> ;			  DL > 80H - DISK				       :
  5269                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5270                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5271                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5272                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5273                              <1> ;	(AH)= 06H  UNUSED						       :
  5274                              <1> ;	(AH)= 07H  UNUSED						       :
  5275                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5276                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5277                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5278                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5279                              <1> ;	(AH)= 0AH  READ LONG						       :
  5280                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5281                              <1> ;	(AH)= 0CH  SEEK 						       :
  5282                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5283                              <1> ;	(AH)= 0EH  UNUSED						       :
  5284                              <1> ;	(AH)= 0FH  UNUSED						       :
  5285                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5286                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5287                              <1> ;	(AH)= 12H  UNUSED						       :
  5288                              <1> ;	(AH)= 13H  UNUSED						       :
  5289                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5290                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5291                              <1> ;									       :
  5292                              <1> ;-------------------------------------------------------------------------------
  5293                              <1> ;									       :
  5294                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5295                              <1> ;									       :
  5296                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5297                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5298                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5299                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5300                              <1> ;									       :
  5301                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5302                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5303                              <1> ;				 (10 BITS TOTAL)			       :
  5304                              <1> ;									       :
  5305                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5306                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5307                              <1> ;									       :
  5308                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5309                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5310                              <1> ;									       :
  5311                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5312                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5313                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5314                              <1> ;			       80H FOR A BAD SECTOR			       :
  5315                              <1> ;			   N = SECTOR NUMBER				       :
  5316                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5317                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5318                              <1> ;									       :
  5319                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5320                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5321                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5322                              <1> ;									       :
  5323                              <1> ;-------------------------------------------------------------------------------
  5324                              <1> 
  5325                              <1> ;-------------------------------------------------------------------------------
  5326                              <1> ; OUTPUT								       :
  5327                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5328                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5329                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5330                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5331                              <1> ;									       :
  5332                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5333                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5334                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5335                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5336                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5337                              <1> ;		REWRITTEN.						       :
  5338                              <1> ;									       :
  5339                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5340                              <1> ;	   INPUT:							       :
  5341                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5342                              <1> ;	   OUTPUT:							       :
  5343                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5344                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5345                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5346                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5347                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5348                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5349                              <1> ;									       :
  5350                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5351                              <1> ;									       :
  5352                              <1> ;	AH = 0 - NOT PRESENT						       :
  5353                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5354                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5355                              <1> ;	     3 - FIXED DISK						       :
  5356                              <1> ;									       :
  5357                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5358                              <1> ;									       :
  5359                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5360                              <1> ;	INFORMATION.							       :
  5361                              <1> ;									       :
  5362                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5363                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5364                              <1> ;									       :
  5365                              <1> ;-------------------------------------------------------------------------------
  5366                              <1> 
  5367                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5368                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5369                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5370                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5371                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5372                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5373                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5374                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5375                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5376                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5377                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5378                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5379                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5380                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5381                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5382                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5383                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5384                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5385                              <1> 
  5386                              <1> ;--------------------------------------------------------
  5387                              <1> ;							:
  5388                              <1> ; FIXED DISK PARAMETER TABLE				:
  5389                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5390                              <1> ;							:
  5391                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5392                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5393                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5394                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5395                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5396                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5397                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5398                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5399                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5400                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5401                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5402                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5403                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5404                              <1> ;							:
  5405                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5406                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5407                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5408                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5409                              <1> ;							:
  5410                              <1> ;--------------------------------------------------------
  5411                              <1> 
  5412                              <1> ;--------------------------------------------------------
  5413                              <1> ;							:
  5414                              <1> ; HARDWARE SPECIFIC VALUES				:
  5415                              <1> ;							:
  5416                              <1> ;  -  CONTROLLER I/O PORT				:
  5417                              <1> ;							:
  5418                              <1> ;     > WHEN READ FROM: 				:
  5419                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5420                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5421                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5422                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5423                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5424                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5425                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5426                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5427                              <1> ;							:
  5428                              <1> ;     > WHEN WRITTEN TO:				:
  5429                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5430                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5431                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5432                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5433                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5434                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5435                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5436                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5437                              <1> ;							:
  5438                              <1> ;--------------------------------------------------------
  5439                              <1> 
  5440                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5441                              <1> ;HF1_PORT	equ	0170h	
  5442                              <1> ;HF_REG_PORT	EQU	03F6H
  5443                              <1> ;HF1_REG_PORT	equ	0376h
  5444                              <1> 
  5445                              <1> HDC1_BASEPORT	equ	1F0h
  5446                              <1> HDC2_BASEPORT	equ	170h		
  5447                              <1> 
  5448                              <1> align 2
  5449                              <1> 
  5450                              <1> ;-----		STATUS REGISTER
  5451                              <1> 
  5452                              <1> ST_ERROR	EQU	00000001B	;
  5453                              <1> ST_INDEX	EQU	00000010B	;
  5454                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5455                              <1> ST_DRQ		EQU	00001000B	;
  5456                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5457                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5458                              <1> ST_READY	EQU	01000000B	;
  5459                              <1> ST_BUSY 	EQU	10000000B	;
  5460                              <1> 
  5461                              <1> ;-----		ERROR REGISTER
  5462                              <1> 
  5463                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5464                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5465                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5466                              <1> ;		EQU	00001000B	; NOT USED
  5467                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5468                              <1> ;		EQU	00100000B	; NOT USED
  5469                              <1> ERR_DATA_ECC	EQU	01000000B
  5470                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5471                              <1> 
  5472                              <1> 
  5473                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5474                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5475                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5476                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5477                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5478                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5479                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5480                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5481                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5482                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5483                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5484                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5485                              <1> 
  5486                              <1> ;MAX_FILE	EQU	2
  5487                              <1> ;S_MAX_FILE	EQU	2
  5488                              <1> MAX_FILE	equ	4		; 22/12/2014
  5489                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5490                              <1> 
  5491                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5492                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5493                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5494                              <1> 
  5495                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5496                              <1> 
  5497                              <1> ;-----		COMMAND BLOCK REFERENCE
  5498                              <1> 
  5499                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5500                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5501                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5502                              <1> ; 19/12/2014
  5503                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5504                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5505                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5506                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5507                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5508                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5509                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5510                              <1> 
  5511                              <1> align 2
  5512                              <1> 
  5513                              <1> ;----------------------------------------------------------------
  5514                              <1> ; FIXED DISK I/O SETUP						:
  5515                              <1> ;								:
  5516                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5517                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5518                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5519                              <1> ;								:
  5520                              <1> ;----------------------------------------------------------------
  5521                              <1> 
  5522                              <1> DISK_SETUP:
  5523                              <1> 	;CLI
  5524                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5525                              <1> 	;xor	ax,ax
  5526                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5527                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5528                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5529                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5530                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5531                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5532                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5533                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5534                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5535                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5536                              <1> 	;;MOV	[HDISK_INT+2],CS
  5537                              <1> 	;mov	[HDISK_INT1+2],CS
  5538                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5539                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5540                              <1> 	;mov	[HDISK_INT2+2],CS
  5541                              <1> 	;
  5542                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5543                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5544                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5545                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5546                              <1> 	;push	cs
  5547                              <1> 	;pop	ds
  5548                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5549                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5550 000025C2 C705[846B0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5550 000025CA 0900                <1>
  5551                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5552                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5553 000025CC C705[886B0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5553 000025D4 0900                <1>
  5554                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5555                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5556 000025D6 C705[8C6B0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5556 000025DE 0900                <1>
  5557                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5558                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5559 000025E0 C705[906B0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5559 000025E8 0900                <1>
  5560                              <1> 	;
  5561                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5562                              <1> 	;;;AND	AL,0BFH
  5563                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5564                              <1> 	;;;JMP	$+2
  5565                              <1> 	;;IODELAY
  5566                              <1> 	;;OUT	INTB01,AL
  5567                              <1> 	;;IODELAY
  5568                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5569                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5570                              <1> 	;;;JMP	$+2
  5571                              <1> 	;;IODELAY
  5572                              <1> 	;;OUT	INTA01,AL
  5573                              <1> 	;
  5574                              <1> 	;STI
  5575                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5576                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5577                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5578                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5579                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5580                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5581                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5582                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5583                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5584                              <1> 	;mov	si, hd0_type
  5585 000025EA BE[E0650000]        <1> 	mov	esi, hd0_type
  5586                              <1> 	;mov	cx, 4
  5587 000025EF B904000000          <1> 	mov	ecx, 4
  5588                              <1> hde_l:
  5589 000025F4 AC                  <1> 	lodsb
  5590 000025F5 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5591 000025F7 7206                <1> 	jb	short _L4
  5592 000025F9 FE05[806B0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5593                              <1> _L4: ; 26/02/2015
  5594 000025FF E2F3                <1> 	loop	hde_l	
  5595                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5596                              <1> ;L4:
  5597                              <1> 	; 
  5598                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5599                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5600                              <1> 	;;mov 	cl, 3
  5601                              <1> 	;;
  5602                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5603                              <1> ;;hdc_dl:
  5604                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5605                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5606                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5607                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5608                              <1> 	;;jnc	short hdc_reset0
  5609                              <1> 	;;loop	hdc_dl
  5610                              <1> 	;;; 27/12/2014
  5611                              <1> 	;;stc
  5612                              <1> 	;;retn
  5613                              <1> 	;
  5614                              <1> ;;hdc_reset0:
  5615                              <1> 	; 18/01/2015
  5616 00002601 8A0D[806B0000]      <1> 	mov	cl, [HF_NUM]
  5617 00002607 20C9                <1> 	and	cl, cl
  5618 00002609 740D                <1> 	jz	short POD_DONE
  5619                              <1> 	;
  5620 0000260B B27F                <1> 	mov	dl, 7Fh
  5621                              <1> hdc_reset1:
  5622 0000260D FEC2                <1> 	inc	dl
  5623                              <1> 	;; 31/12/2015
  5624                              <1> 	;;push	dx
  5625                              <1> 	;;push	cx
  5626                              <1> 	;;push	ds
  5627                              <1> 	;;sub	ax, ax
  5628                              <1> 	;;mov	ds, ax
  5629                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5630                              <1> 	;;pop	ds
  5631                              <1> 	;;MOV	BX,AX
  5632                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5633                              <1> 	;;MOV	CX,AX
  5634                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5635                              <1> 	;;
  5636                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5637                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5638                              <1> 	;;pop	cx
  5639                              <1> 	;;pop	dx
  5640                              <1> 	;;
  5641                              <1> 	; 18/01/2015
  5642 0000260F B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5643                              <1> 	;int	13h
  5644 00002611 E8A4FFFFFF          <1> 	call	int13h
  5645 00002616 E2F5                <1> 	loop	hdc_reset1
  5646                              <1> POD_DONE:
  5647 00002618 C3                  <1> 	RETn
  5648                              <1> 
  5649                              <1> ;;-----	POD_ERROR
  5650                              <1> 
  5651                              <1> ;;CTL_ERRX:
  5652                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5653                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5654                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5655                              <1> ;	;JMP	short POD_DONE
  5656                              <1> 
  5657                              <1> ;;HD_RESET_1:
  5658                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5659                              <1> ;;	;PUSH	CX
  5660                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5661                              <1> ;;	INT	13H
  5662                              <1> ;;	JC	short RES_2
  5663                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5664                              <1> ;;	INT	13H
  5665                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5666                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5667                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5668                              <1> ;;					; (30 seconds)		
  5669                              <1> ;;	;cmc
  5670                              <1> ;;	;JNC	short RES_1
  5671                              <1> ;;	jb	short RES_1
  5672                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5673                              <1> ;;	;TEST	DL,1
  5674                              <1> ;;	;JNZ	RES_E1
  5675                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5676                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5677                              <1> ;;	;JMP	SHORT RES_E1
  5678                              <1> ;;RES_ER: ; 22/12/2014
  5679                              <1> ;;RES_OK:
  5680                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5681                              <1> ;;	;POP	BX
  5682                              <1> ;;	RETn
  5683                              <1> ;;
  5684                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5685                              <1> ;;	INT	13H
  5686                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5687                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5688                              <1> ;;	INT	13H
  5689                              <1> ;;	JC	short RES_ER
  5690                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5691                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5692                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5693                              <1> ;;	INT	13H
  5694                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5695                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5696                              <1> ;;	JE	short RES_OK
  5697                              <1> ;;	CMP	AH,DATA_CORRECTED
  5698                              <1> ;;	JE	short RES_OK
  5699                              <1> ;;	CMP	AH,BAD_ECC
  5700                              <1> ;;	JE	short RES_OK
  5701                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5702                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5703                              <1> ;;					; (60 seconds)		
  5704                              <1> ;;	cmc
  5705                              <1> ;;	JC	short RES_ER		; FAILED
  5706                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5707                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5708                              <1> ;;	AND	AL,3FH
  5709                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5710                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5711                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5712                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5713                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5714                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5715                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5716                              <1> ;;	;TEST	DL,1
  5717                              <1> ;;	;JNZ	short RES_E1
  5718                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5719                              <1> ;;;RES_E1:
  5720                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5721                              <1> ;;;RES_OK:
  5722                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5723                              <1> ;;	;POP	BX
  5724                              <1> ;;	;RETn
  5725                              <1> ;
  5726                              <1> ;;SET_FAIL:
  5727                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5728                              <1> ;	;CALL	CMOS_READ
  5729                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5730                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5731                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5732                              <1> ;	;RETn
  5733                              <1> ;
  5734                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5735                              <1> ;	;POP	AX			; SAVE RETURN
  5736                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5737                              <1> ;	;POP	BX
  5738                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5739                              <1> ;	;PUSH	CX
  5740                              <1> ;	;PUSH	AX
  5741                              <1> ;	;push	ds
  5742                              <1> ;	;xor	ax, ax
  5743                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5744                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5745                              <1> ;	;				; BX = START TIME
  5746                              <1> ;	;				; CX = END TIME
  5747                              <1> ;	;pop	ds
  5748                              <1> ;	;CMP	BX,CX
  5749                              <1> ;	;JB	short TCHK1		; START < END
  5750                              <1> ;	;CMP	BX,AX
  5751                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5752                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5753                              <1> ;;TCHK1: CMP	AX,BX
  5754                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5755                              <1> ;;TCHK2: CMP	AX,CX
  5756                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5757                              <1> ;;					; OR CURRENT < END < START
  5758                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5759                              <1> ;;	RETn
  5760                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5761                              <1> ;;	RETn
  5762                              <1> ;;
  5763                              <1> ;;int_13h:
  5764                              <1> 
  5765                              <1> ;----------------------------------------
  5766                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5767                              <1> ;----------------------------------------
  5768                              <1> 
  5769                              <1> DISK_IO:
  5770 00002619 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5771                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5772                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5773                              <1> 	;;call	int40h
  5774                              <1> 	;jb	DISKETTE_IO_1
  5775                              <1> 	; 24/12/2021
  5776 0000261C 7305                <1> 	jnb	short A1
  5777 0000261E E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5778                              <1> ;RET_2:
  5779                              <1> 	;RETf	2			; BACK TO CALLER
  5780                              <1> ;	retf	4
  5781                              <1> A1:
  5782 00002623 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5783                              <1> 	;; 04/01/2015
  5784                              <1> 	;;OR	AH,AH
  5785                              <1> 	;;JNZ	short A2
  5786                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5787                              <1> 	;;SUB	AH,AH
  5788 00002624 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5789 00002627 772E                <1> 	JA	short RET_2
  5790                              <1> 	; 18/01/2015
  5791 00002629 08E4                <1> 	or	ah,ah
  5792 0000262B 742D                <1> 	jz	short A4
  5793 0000262D 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5794 00002630 7504                <1> 	jne	short A2
  5795 00002632 28E4                <1> 	sub	ah,ah	; Reset
  5796 00002634 EB24                <1> 	jmp	short A4
  5797                              <1> A2:
  5798 00002636 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5799                              <1> 	;JNZ	short A3
  5800                              <1>         ;JMP    GET_PARM_N
  5801                              <1> 	;je	GET_PARM_N
  5802                              <1> 	; 24/12/2021
  5803 00002639 7505                <1> 	jne	short A3
  5804 0000263B E90D030000          <1> 	jmp	GET_PARM_N
  5805                              <1> A3:	
  5806 00002640 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5807                              <1> 	;JNZ	short A4
  5808                              <1>         ;JMP    READ_DASD_TYPE
  5809                              <1> 	;je	READ_DASD_TYPE
  5810                              <1> 	; 24/12/2021
  5811 00002643 7505                <1> 	jne	short A3_A4
  5812 00002645 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5813                              <1> A3_A4:
  5814                              <1> 	; 02/02/2015
  5815 0000264A 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5816                              <1> 	; 12/01/2015
  5817 0000264D F5                  <1> 	cmc
  5818 0000264E 730A                <1> 	jnc	short A4
  5819                              <1> 	; 30/01/2015
  5820                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5821 00002650 C605[7F6B0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5822                              <1> 	;jmp	short RET_2
  5823                              <1> RET_2:
  5824 00002657 CA0400              <1> 	retf	4
  5825                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5826 0000265A C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5827 0000265E 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5828 0000265F 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5829 00002660 52                  <1> 	PUSH	eDX
  5830 00002661 1E                  <1> 	PUSH	DS
  5831 00002662 06                  <1> 	PUSH	ES
  5832 00002663 56                  <1> 	PUSH	eSI
  5833 00002664 57                  <1> 	PUSH	eDI
  5834                              <1> 	;;04/01/2015
  5835                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5836                              <1> 	;;JNZ	short A5
  5837                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5838                              <1> ;;A5:	
  5839                              <1> 	;push	cs
  5840                              <1> 	;pop	ds
  5841                              <1> 	; 21/02/2015
  5842                              <1> 	;push	ax
  5843                              <1> 	; 24/12/2021
  5844 00002665 50                  <1> 	push	eax
  5845 00002666 66B81000            <1> 	mov	ax, KDATA
  5846 0000266A 8ED8                <1> 	mov	ds, ax
  5847 0000266C 8EC0                <1> 	mov	es, ax	
  5848                              <1> 	;pop	ax
  5849                              <1> 	; 24/12/2021
  5850 0000266E 58                  <1> 	pop	eax
  5851 0000266F E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5852                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5853 00002674 8A25[7F6B0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5854 0000267A 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5855 0000267D F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5856 0000267E 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5857 0000267F 5E                  <1> 	POP	eSI
  5858 00002680 07                  <1>         POP     ES
  5859 00002681 1F                  <1>         POP     DS
  5860 00002682 5A                  <1> 	POP	eDX
  5861 00002683 59                  <1> 	POP	eCX
  5862 00002684 5B                  <1> 	POP	eBX
  5863 00002685 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5864                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5865 00002686 CA0400              <1> 	retf	4
  5866                              <1> ; 21/02/2015
  5867                              <1> ;       dw --> dd
  5868                              <1> M1:					; FUNCTION TRANSFER TABLE
  5869 00002689 [42280000]          <1> 	dd	DISK_RESET		; 000H
  5870 0000268D [B7280000]          <1> 	dd	RETURN_STATUS		; 001H
  5871 00002691 [C4280000]          <1> 	dd	DISK_READ		; 002H
  5872 00002695 [CD280000]          <1> 	dd	DISK_WRITE		; 003H
  5873 00002699 [D6280000]          <1> 	dd	DISK_VERF		; 004H
  5874 0000269D [EE280000]          <1> 	dd	FMT_TRK 		; 005H
  5875 000026A1 [38280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5876 000026A5 [38280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5877 000026A9 [38280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5878 000026AD [AF290000]          <1> 	dd	INIT_DRV		; 009H
  5879 000026B1 [0E2A0000]          <1> 	dd	RD_LONG 		; 00AH
  5880 000026B5 [172A0000]          <1> 	dd	WR_LONG 		; 00BH
  5881 000026B9 [202A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5882 000026BD [42280000]          <1> 	dd	DISK_RESET		; 00DH
  5883 000026C1 [38280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5884 000026C5 [38280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5885 000026C9 [482A0000]          <1> 	dd	TST_RDY 		; 010H
  5886 000026CD [6C2A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5887 000026D1 [38280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5888 000026D5 [38280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5889 000026D9 [A22A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5890                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5891 000026DD [38280000]          <1> 	dd	BAD_COMMAND		; 015h
  5892 000026E1 [38280000]          <1> 	dd	BAD_COMMAND		; 016h
  5893 000026E5 [38280000]          <1> 	dd	BAD_COMMAND		; 017h
  5894 000026E9 [38280000]          <1> 	dd	BAD_COMMAND		; 018h
  5895 000026ED [38280000]          <1> 	dd	BAD_COMMAND		; 019h
  5896 000026F1 [38280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5897 000026F5 [C4280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5898 000026F9 [CD280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5899                              <1> M1L     EQU    $-M1
  5900                              <1> 
  5901                              <1> DISK_IO_CONT:
  5902                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5903 000026FD 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5904                              <1> 	;;JNZ	short SU0
  5905                              <1>         ;;JMP	RETURN_STATUS
  5906                              <1> 	;je	RETURN_STATUS
  5907                              <1> 	; 24/12/2021
  5908 00002700 7505                <1> 	jne	short SU0
  5909 00002702 E9B0010000          <1> 	jmp	RETURN_STATUS
  5910                              <1> SU0:
  5911 00002707 C605[7F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5912                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5913                              <1> 	;mov	si, bx ;; 14/02/2015
  5914 0000270E 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5915 00002710 8A1D[806B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5916                              <1> 	;; 04/01/2015
  5917                              <1> 	;;PUSH	AX
  5918 00002716 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5919                              <1> 					; (get drive number as 0 to 3)
  5920 00002719 38D3                <1> 	CMP	BL,DL
  5921                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5922                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5923                              <1> 	; 24/12/2021
  5924 0000271B 7705                <1> 	ja	short su0_su1
  5925 0000271D E916010000          <1> 	jmp	BAD_COMMAND
  5926                              <1> su0_su1:
  5927                              <1>         ;;03/01/2015
  5928 00002722 29DB                <1> 	sub	ebx, ebx
  5929 00002724 88D3                <1> 	mov	bl, dl
  5930                              <1> 	;sub	bh, bh
  5931 00002726 883D[946B0000]      <1> 	mov	[LBAMode], bh 	; 0
  5932                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5933                              <1> 	;test	byte [ebx+hd0_type], 1
  5934                              <1> 	;jz	short su1		; no
  5935                              <1> 	;inc	byte [LBAMode]
  5936                              <1> ;su1:
  5937                              <1> 	; 21/02/2015 (32 bit modification)
  5938                              <1> 	; 04/01/2015
  5939                              <1> 	;push	ax ; ***
  5940                              <1> 	; 24/12/2021
  5941 0000272C 50                  <1> 	push	eax ; ***
  5942                              <1> 	;PUSH	ES ; **
  5943                              <1> 	;PUSH	DX ; *
  5944                              <1> 	; 24/12/2021
  5945 0000272D 52                  <1> 	push	edx ; *
  5946                              <1> 	;push	ax
  5947 0000272E 50                  <1> 	push	eax
  5948 0000272F E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5949                              <1> 	; 02/02/2015
  5950                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5951 00002734 668B4310            <1> 	mov	ax, [ebx+16]
  5952 00002738 66A3[D4650000]      <1> 	mov	[HF_PORT], ax
  5953                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5954 0000273E 668B5312            <1> 	mov	dx, [ebx+18]
  5955 00002742 668915[D6650000]    <1> 	mov	[HF_REG_PORT], dx
  5956                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5957 00002749 8A4314              <1> 	mov	al, [ebx+20]
  5958                              <1> 	; 23/02/2015
  5959 0000274C A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5960 0000274E 7406                <1> 	jz 	short su1
  5961 00002750 FE05[946B0000]      <1> 	inc	byte [LBAMode] ; 1 
  5962                              <1> su1: 	 
  5963 00002756 C0E804              <1> 	shr 	al, 4
  5964 00002759 2401                <1> 	and	al, 1			
  5965 0000275B A2[D8650000]        <1> 	mov	[hf_m_s], al 
  5966                              <1> 	;
  5967                              <1> 	; 03/01/2015
  5968                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5969 00002760 8A4308              <1> 	mov	al, [ebx+8]
  5970                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5971 00002763 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  5972                              <1> 					; Control Byte:  (= 08h, here)
  5973                              <1> 					; bit 0 - 0
  5974                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5975                              <1> 					; bit 2 - SRST (software RESET)
  5976                              <1> 					; bit 3 - use extra heads (8 to 15)
  5977                              <1> 					;         -always set to 1-	
  5978                              <1> 					; (bits 3 to 7 are reserved
  5979                              <1> 					;          for ATA devices)
  5980 00002764 8A25[816B0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5981 0000276A 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  5982 0000276D 08C4                <1> 	OR	AH,AL
  5983 0000276F 8825[816B0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  5984                              <1> 	; 04/01/2015
  5985                              <1> 	;pop	ax
  5986                              <1> 	; 24/12/2021
  5987 00002775 58                  <1> 	pop	eax
  5988                              <1> 	;pop	dx ; * ;; 14/02/2015
  5989                              <1> 	; 24/12/2021
  5990 00002776 5A                  <1> 	pop	edx ; *
  5991 00002777 20E4                <1> 	and	ah, ah	; Reset function ?
  5992 00002779 7506                <1> 	jnz	short su2
  5993                              <1> 	;;pop	dx ; * ;; 14/02/2015
  5994                              <1> 	;pop	es ; **
  5995                              <1> 	;pop	ax ; ***
  5996                              <1> 	; 24/12/2021
  5997 0000277B 58                  <1> 	pop	eax ; ***	
  5998                              <1> 	;;pop	bx
  5999 0000277C E9C1000000          <1>         jmp     DISK_RESET
  6000                              <1> su2:
  6001 00002781 803D[946B0000]00    <1> 	cmp	byte [LBAMode], 0
  6002 00002788 765E                <1> 	jna	short su3
  6003                              <1> 	;
  6004                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6005 0000278A 80FC1B              <1> 	cmp	ah, 1Bh
  6006 0000278D 720B                <1> 	jb	short lbarw1
  6007 0000278F 80FC1C              <1> 	cmp	ah, 1Ch
  6008 00002792 7759                <1> 	ja 	short invldfnc
  6009                              <1> 	;;pop	dx ; * ; 14/02/2015
  6010                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6011 00002794 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6012                              <1> 	;; 14/02/2015
  6013 00002796 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6014                              <1> 	;;mov	dx, bx
  6015                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6016                              <1> 	;;mov	bx, di
  6017                              <1> 	;mov	si, di ; Buffer offset
  6018 00002798 EB2E                <1> 	jmp	short lbarw2
  6019                              <1> lbarw1:
  6020                              <1> 	; convert CHS to LBA
  6021                              <1> 	;
  6022                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6023                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6024                              <1> 	;	+ Sector - 1
  6025                              <1> 	;push	dx ; * ;; 14/02/2015
  6026                              <1> 	; 24/12/2021
  6027 0000279A 52                  <1> 	push	edx ; *
  6028                              <1> 	;xor	dh, dh
  6029 0000279B 31D2                <1> 	xor	edx, edx
  6030                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6031 0000279D 8A530E              <1> 	mov	dl, [ebx+14]
  6032                              <1> 	;xor	ah, ah
  6033 000027A0 31C0                <1> 	xor	eax, eax
  6034                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6035 000027A2 8A4302              <1> 	mov	al, [ebx+2]
  6036 000027A5 FEC8                <1> 	dec	al
  6037                              <1> 	;inc	ax		; 0 =  256
  6038 000027A7 40                  <1> 	inc	eax ; 24/12/2021
  6039 000027A8 66F7E2              <1> 	mul 	dx
  6040                              <1> 		; AX = # of Heads" * Sectors/Track
  6041 000027AB 6689CA              <1> 	mov	dx, cx
  6042                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6043 000027AE 83E13F              <1> 	and	ecx, 3fh
  6044 000027B1 86D6                <1> 	xchg	dl, dh
  6045 000027B3 C0EE06              <1> 	shr	dh, 6
  6046                              <1> 		; DX = cylinder (0 to 1023)
  6047                              <1> 	;mul 	dx
  6048                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6049 000027B6 F7E2                <1> 	mul	edx
  6050 000027B8 FEC9                <1> 	dec	cl  ; sector - 1
  6051                              <1> 	;add	ax, cx
  6052                              <1> 	;adc	dx, 0
  6053                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6054 000027BA 01C8                <1> 	add	eax, ecx
  6055                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6056                              <1> 	; 24/12/2021
  6057 000027BC 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6058                              <1> 	;push	dx
  6059                              <1> 	;push	ax
  6060 000027BD 50                  <1> 	push	eax
  6061                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6062 000027BE 8A430E              <1> 	mov	al, [ebx+14]
  6063 000027C1 F6E5                <1> 	mul	ch
  6064                              <1> 		; AX = Head * Sectors/Track
  6065 000027C3 6699                <1>         cwd
  6066                              <1> 	;pop	dx
  6067 000027C5 5A                  <1> 	pop	edx
  6068                              <1> 	;add	ax, dx
  6069                              <1> 	;pop	dx
  6070                              <1> 	;adc	dx, 0 ; add carry bit
  6071 000027C6 01D0                <1> 	add	eax, edx
  6072                              <1> lbarw2:
  6073 000027C8 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6074 000027CA 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6075 000027CC C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6076                              <1> 				; NOTE: Features register (1F1h, 171h)
  6077                              <1> 				; is not used for ATA device R/W functions. 
  6078                              <1> 				; It is old/obsolete 'write precompensation'
  6079                              <1> 				; register and error register
  6080                              <1> 				; for old ATA/IDE devices.
  6081                              <1> 	; 18/01/2014
  6082                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6083 000027D0 8A0D[D8650000]      <1> 	mov	cl, [hf_m_s]
  6084                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6085                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6086                              <1> 				; bit 6 = 1 = LBA mode
  6087                              <1> 				; bit 7 = 1
  6088 000027D6 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6089                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6090 000027D9 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6091 000027DE C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6092                              <1> 	;or	dh, ch
  6093 000027E1 09C8                <1> 	or	eax, ecx	
  6094                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6095                              <1> 				  ; (Sector Number Register)
  6096                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6097                              <1> 				  ; (Cylinder Low Register)
  6098                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6099                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6100                              <1> 				  ; (Cylinder High Register)
  6101                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6102                              <1> 				  ; (Drive/Head Register)
  6103                              <1> 	
  6104                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6105 000027E3 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6106                              <1> 	;14/02/2015
  6107                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6108 000027E6 EB37                <1> 	jmp	short su4
  6109                              <1> su3:
  6110                              <1> 	; 02/02/2015 
  6111                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6112 000027E8 80FC14              <1> 	cmp 	ah, 14h
  6113 000027EB 7603                <1> 	jna 	short chsfnc
  6114                              <1> invldfnc:
  6115                              <1>         ; 14/02/2015  
  6116                              <1> 	;pop	es ; **
  6117                              <1>         ;pop	ax ; ***
  6118                              <1>         ; 24/12/2021
  6119 000027ED 58                  <1> 	pop	eax ; ***
  6120                              <1> 	;jmp	short BAD_COMMAND_POP
  6121 000027EE EB48                <1>         jmp     short BAD_COMMAND
  6122                              <1> chsfnc:	
  6123                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6124 000027F0 668B4305            <1> 	mov	ax, [ebx+5]
  6125 000027F4 66C1E802            <1> 	SHR	AX,2
  6126 000027F8 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6127                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6128                              <1> 	;;PUSH	DX
  6129                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6130                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6131                              <1> 	;;POP	DX ; * 
  6132                              <1> 	;;POP	ES ; **
  6133                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6134                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6135                              <1> 	;;OR	AH,AL
  6136                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6137                              <1> 	;
  6138 000027FB 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6139 000027FD 243F                <1> 	AND	AL,3FH
  6140 000027FF 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6141 00002802 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6142 00002805 88C8                <1> 	MOV	AL,CL
  6143 00002807 C0E806              <1> 	SHR	AL,6
  6144 0000280A 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6145                              <1> 	;;05/01/2015
  6146                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6147 0000280D A0[D8650000]        <1> 	mov	al, [hf_m_s]
  6148 00002812 C0E004              <1> 	SHL	AL,4
  6149 00002815 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6150 00002818 08F0                <1> 	OR	AL,DH
  6151                              <1> 	;OR	AL,80H or 20H
  6152 0000281A 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6153 0000281C 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6154                              <1> su4:
  6155                              <1> 	;POP	ES ; **
  6156                              <1>         ;; 14/02/2015
  6157                              <1>         ;;POP   AX
  6158                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6159                              <1>         ;;PUSH  AX
  6160                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6161                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6162                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6163                              <1> 	;pop     ax ; ***
  6164                              <1> 	; 24/12/2021
  6165 0000281F 58                  <1> 	pop	eax ; ***
  6166 00002820 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6167 00002823 29DB                <1>         sub	ebx, ebx
  6168 00002825 88E3                <1> 	mov     bl, ah
  6169                              <1>         ;xor	bh, bh
  6170                              <1>         ;sal	bx, 1
  6171 00002827 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6172                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6173                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6174                              <1>         ;;JNB   short BAD_COMMAND_POP
  6175                              <1>         ;cmp	bx, M1L
  6176 0000282B 83FB74              <1> 	cmp	ebx, M1L
  6177 0000282E 7308                <1> 	jnb	short BAD_COMMAND
  6178                              <1>         ;xchg	bx, si
  6179 00002830 87DE                <1>         xchg	ebx, esi
  6180                              <1> 	;;;POP	AX			; RESTORE AX
  6181                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6182                              <1> 	
  6183                              <1> 	;;PUSH	CX
  6184                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6185                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6186                              <1> 	;SHR	CX,4
  6187                              <1> 	;MOV	AX,ES
  6188                              <1> 	;ADD	AX,CX
  6189                              <1> 	;MOV	ES,AX
  6190                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6191                              <1> 	;;POP	AX
  6192                              <1> 	;;POP	CX
  6193                              <1> 	;;JMP	word [CS:SI+M1]
  6194                              <1> 	;jmp	word [SI+M1]
  6195 00002832 FFA6[89260000]      <1> 	jmp	dword [esi+M1]
  6196                              <1> ;;BAD_COMMAND_POP:
  6197                              <1> ;;	POP	AX
  6198                              <1> ;;	POP	BX
  6199                              <1> BAD_COMMAND:
  6200 00002838 C605[7F6B0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6201 0000283F B000                <1> 	MOV	AL,0
  6202 00002841 C3                  <1> 	RETn
  6203                              <1> 
  6204                              <1> ;----------------------------------------
  6205                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6206                              <1> ;----------------------------------------
  6207                              <1> 
  6208                              <1> ; 18-1-2015 : one controller reset (not other one)
  6209                              <1> 
  6210                              <1> DISK_RESET:
  6211 00002842 FA                  <1> 	CLI
  6212 00002843 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6213                              <1> 	;JMP	$+2
  6214                              <1> 	IODELAY
  2101 00002845 EB00                <2>  jmp short $+2
  2102 00002847 EB00                <2>  jmp short $+2
  6215                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6216 00002849 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6217 0000284B E6A1                <1> 	OUT	INTB01,AL
  6218 0000284D FB                  <1> 	STI				; START INTERRUPTS
  6219                              <1> 	; 14/02/2015
  6220                              <1> 	;mov	di, dx
  6221                              <1> 	; 24/12/2021
  6222 0000284E 89D7                <1> 	mov	edi, edx	
  6223                              <1> 	; 04/01/2015
  6224                              <1> 	;xor	di,di
  6225                              <1> drst0:
  6226 00002850 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6227                              <1> 	;MOV	DX,HF_REG_PORT
  6228 00002852 668B15[D6650000]    <1> 	MOV	DX,[HF_REG_PORT]
  6229 00002859 EE                  <1> 	OUT	DX,AL			; RESET
  6230                              <1> ;	MOV	CX,10			; DELAY COUNT
  6231                              <1> ;DRD:	DEC	CX
  6232                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6233                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6234 0000285A B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6235 0000285F E872ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6236                              <1>                                         ; 40 micro seconds)
  6237 00002864 A0[816B0000]        <1> 	mov	al,[CONTROL_BYTE]
  6238 00002869 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6239 0000286B EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6240 0000286C E807040000          <1> 	CALL	NOT_BUSY
  6241 00002871 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6242 00002873 668B15[D4650000]    <1> 	MOV	DX,[HF_PORT]
  6243 0000287A FEC2                <1> 	inc	dl  ; HF_PORT+1
  6244                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6245                              <1>         ;mov	cl, 10
  6246 0000287C B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6247                              <1> drst1:
  6248 00002881 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6249 00002882 3C01                <1> 	CMP	AL,1
  6250                              <1> 	; 04/01/2015
  6251 00002884 740A                <1> 	jz	short drst2
  6252                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6253                              <1>         	; Drive/Head Register - bit 4
  6254 00002886 E2F9                <1> 	loop	drst1
  6255                              <1> DRERR:	
  6256 00002888 C605[7F6B0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6257 0000288F C3                  <1> 	RETn
  6258                              <1> drst2:
  6259                              <1> 	; 14/02/2015
  6260                              <1> 	;mov	dx, di
  6261                              <1> 	; 24/12/2021
  6262 00002890 89FA                <1> 	mov	edx, edi
  6263                              <1> ;drst3:
  6264                              <1> ;	; 05/01/2015
  6265                              <1> ;	shl 	di,1
  6266                              <1> ;	; 04/01/2015
  6267                              <1> ;	mov	ax,[di+hd_cports]
  6268                              <1> ;	cmp	ax,[HF_REG_PORT]
  6269                              <1> ;	je	short drst4
  6270                              <1> ;	mov	[HF_REG_PORT], ax
  6271                              <1> ;	; 03/01/2015
  6272                              <1> ;	mov	ax,[di+hd_ports]
  6273                              <1> ;       mov     [HF_PORT], ax
  6274                              <1> ;	; 05/01/2014
  6275                              <1> ;	shr	di,1
  6276                              <1> ;	; 04/01/2015
  6277                              <1> ;	jmp	short drst0	; reset other controller
  6278                              <1> ;drst4:
  6279                              <1> ;	; 05/01/2015
  6280                              <1> ;	shr	di,1
  6281                              <1> ;	mov	al,[di+hd_dregs]
  6282                              <1> ;	and	al,10h ; bit 4 only
  6283                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6284                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6285                              <1> 	;
  6286 00002892 A0[D8650000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6287 00002897 A801                <1> 	test	al,1
  6288                              <1> ;	jnz	short drst6
  6289 00002899 7516                <1>         jnz     short drst4
  6290 0000289B 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6291                              <1> ;drst5:
  6292                              <1> drst3:
  6293 0000289F E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6294                              <1> 	;mov	dx,di
  6295 000028A4 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6296                              <1> 	; 04/01/2014
  6297                              <1> ;	inc	di
  6298                              <1> ;	mov	dx,di
  6299                              <1> ;	cmp	dl,[HF_NUM]
  6300                              <1> ;	jb	short drst3
  6301                              <1> ;DRE:
  6302 000028A9 C605[7F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6303 000028B0 C3                  <1> 	RETn
  6304                              <1> ;drst6:
  6305                              <1> drst4:		; Drive/Head Register - bit 4
  6306 000028B1 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6307                              <1>         ;jmp    short drst5
  6308 000028B5 EBE8                <1>         jmp     short drst3
  6309                              <1> 
  6310                              <1> ;----------------------------------------
  6311                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6312                              <1> ;----------------------------------------
  6313                              <1> 
  6314                              <1> RETURN_STATUS:
  6315 000028B7 A0[7F6B0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6316 000028BC C605[7F6B0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6317 000028C3 C3                  <1> 	RETn
  6318                              <1> 
  6319                              <1> ;----------------------------------------
  6320                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6321                              <1> ;----------------------------------------
  6322                              <1> 
  6323                              <1> DISK_READ:
  6324 000028C4 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6325 000028C8 E92A020000          <1>         JMP     COMMANDI
  6326                              <1> 
  6327                              <1> ;----------------------------------------
  6328                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6329                              <1> ;----------------------------------------
  6330                              <1> 
  6331                              <1> DISK_WRITE:
  6332 000028CD C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6333 000028D1 E976020000          <1>         JMP     COMMANDO
  6334                              <1> 
  6335                              <1> ;----------------------------------------
  6336                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6337                              <1> ;----------------------------------------
  6338                              <1> 
  6339                              <1> DISK_VERF:
  6340 000028D6 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6341 000028DA E8E4020000          <1> 	CALL	COMMAND
  6342 000028DF 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6343 000028E1 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6344 000028E6 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6345 000028E8 E8E3030000          <1> 	CALL	CHECK_STATUS
  6346                              <1> VERF_EXIT:
  6347 000028ED C3                  <1> 	RETn
  6348                              <1> 
  6349                              <1> ;----------------------------------------
  6350                              <1> ;	FORMATTING	     (AH = 05H) :
  6351                              <1> ;----------------------------------------
  6352                              <1> 
  6353                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6354 000028EE C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6355                              <1> 	;PUSH	ES
  6356                              <1> 	;PUSH	BX
  6357 000028F2 53                  <1> 	push	ebx
  6358 000028F3 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6359                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6360 000028F8 8A430E              <1> 	mov	al, [ebx+14]
  6361 000028FB 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6362 000028FE 5B                  <1> 	pop	ebx
  6363                              <1> 	;POP	BX
  6364                              <1> 	;POP	ES
  6365 000028FF E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6366                              <1> 
  6367                              <1> ;----------------------------------------
  6368                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6369                              <1> ;----------------------------------------
  6370                              <1> 
  6371                              <1> READ_DASD_TYPE:
  6372                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6373 00002904 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6374                              <1> 	;PUSH	ES
  6375 00002905 53                  <1> 	PUSH	eBX
  6376                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6377                              <1> 	;push	cs
  6378                              <1> 	;pop	ds
  6379 00002906 66BB1000            <1>         mov	bx, KDATA
  6380 0000290A 8EDB                <1> 	mov	ds, bx
  6381                              <1> 	;mov	es, bx
  6382 0000290C C605[7F6B0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6383 00002913 8A1D[806B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6384 00002919 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6385 0000291C 38D3                <1> 	CMP	BL,DL
  6386 0000291E 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6387 00002920 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6388                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6389 00002925 8A4302              <1> 	mov	al, [ebx+2]
  6390                              <1> 	;MOV	CL,[ES:BX+14]
  6391 00002928 8A4B0E              <1> 	mov	cl, [ebx+14]
  6392 0000292B F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6393                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6394 0000292D 668B0B              <1> 	mov	cx, [ebx]
  6395                              <1> 	;
  6396                              <1> 	; 02/01/2015 
  6397                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6398                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6399 00002930 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6400                              <1> 	;
  6401 00002932 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6402 00002935 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6403 00002938 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6404                              <1> 	;SUB	AX,AX
  6405 0000293B 28C0                <1> 	sub	al, al
  6406 0000293D B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6407 0000293F 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6408                              <1> 	;POP	ES
  6409 00002940 1F                  <1> 	POP	DS
  6410 00002941 F8                  <1> 	CLC				; CLEAR CARRY
  6411                              <1> 	;RETf	2
  6412 00002942 CA0400              <1> 	retf	4
  6413                              <1> RDT_NOT_PRESENT:
  6414                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6415                              <1> 	; 24/12/2021
  6416 00002945 29C0                <1> 	sub	eax, eax
  6417                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6418                              <1> 	;MOV	DX,AX
  6419 00002947 89C1                <1> 	mov	ecx, eax
  6420 00002949 89C2                <1> 	mov	edx, eax
  6421 0000294B EBF2                <1> 	JMP	short RDT2
  6422                              <1> 
  6423                              <1> ;----------------------------------------
  6424                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6425                              <1> ;----------------------------------------
  6426                              <1> 
  6427                              <1> GET_PARM_N:
  6428                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6429 0000294D 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6430                              <1> 	;PUSH	ES
  6431 0000294E 53                  <1> 	PUSH	eBX
  6432                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6433                              <1> 	;MOV	DS,AX
  6434                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6435                              <1> 	;JZ	short G0
  6436                              <1> 	;LES	BX,@HF1_TBL_VEC
  6437                              <1> 	;JMP	SHORT G1
  6438                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6439                              <1> ;G1:
  6440                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6441                              <1> 	; 22/12/2014
  6442                              <1> 	;push	cs
  6443                              <1> 	;pop	ds
  6444 0000294F 66BB1000            <1> 	mov	bx, KDATA
  6445 00002953 8EDB                <1> 	mov	ds, bx
  6446                              <1> 	;mov	es, bx
  6447                              <1> 	;
  6448 00002955 80EA80              <1> 	SUB	DL,80H
  6449 00002958 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6450 0000295B 7340                <1> 	JAE	short G4
  6451                              <1> 	;
  6452 0000295D 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6453                              <1> 	; 22/12/2014
  6454 0000295F 88D3                <1> 	mov	bl, dl
  6455                              <1> 	;xor	bh, bh  
  6456 00002961 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6457                              <1> 	;add	bx, HF_TBL_VEC
  6458 00002964 81C3[846B0000]      <1> 	add	ebx, HF_TBL_VEC
  6459                              <1> 	;mov	ax, [bx+2]
  6460                              <1> 	;mov	es, ax			; dpt segment
  6461                              <1> 	;mov	bx, [bx]		; dpt offset
  6462 0000296A 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6463                              <1> 
  6464 0000296C C605[7F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6465                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6466 00002973 668B03              <1> 	mov	ax, [ebx]
  6467                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6468 00002976 6648                <1> 	dec	ax			; max. cylinder number
  6469 00002978 88C5                <1> 	MOV	CH,AL
  6470 0000297A 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6471 0000297E 66D1E8              <1> 	SHR	AX,1
  6472 00002981 66D1E8              <1> 	SHR	AX,1
  6473                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6474 00002984 0A430E              <1> 	or	al, [ebx+14]
  6475 00002987 88C1                <1> 	MOV	CL,AL
  6476                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6477 00002989 8A7302              <1> 	mov	dh, [ebx+2]
  6478 0000298C FECE                <1> 	DEC	DH			; 0-N RANGE
  6479 0000298E 8A15[806B0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6480                              <1> 	;SUB	AX,AX
  6481                              <1> 	; 24/12/2021
  6482 00002994 29C0                <1> 	sub	eax, eax
  6483                              <1> 	; 27/12/2014 
  6484                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6485                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6486                              <1> 	;mov	di, bx			; HDPT offset
  6487 00002996 89DF                <1> 	mov	edi, ebx
  6488                              <1> G5:
  6489 00002998 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6490                              <1> 	;POP	ES
  6491 00002999 1F                  <1> 	POP	DS
  6492                              <1> 	;RETf	2
  6493 0000299A CA0400              <1> 	retf	4
  6494                              <1> G4:
  6495 0000299D C605[7F6B0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6496                              <1> 	; 24/12/2021
  6497 000029A4 29C0                <1> 	sub	eax, eax
  6498 000029A6 B407                <1> 	MOV	AH,INIT_FAIL
  6499                              <1> 	;SUB	AL,AL
  6500                              <1> 	;SUB	DX,DX
  6501 000029A8 29D2                <1> 	sub	edx, edx
  6502                              <1> 	;SUB	CX,CX
  6503 000029AA 29C9                <1> 	sub	ecx, ecx
  6504 000029AC F9                  <1> 	STC				; SET ERROR FLAG
  6505 000029AD EBE9                <1> 	JMP	short G5
  6506                              <1> 
  6507                              <1> ;----------------------------------------
  6508                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6509                              <1> ;----------------------------------------
  6510                              <1> 	; 03/01/2015
  6511                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6512                              <1> 	; logical sector per logical track
  6513                              <1> 	; and logical heads - 1 would be set but
  6514                              <1> 	; it is seen as it will be good
  6515                              <1> 	; if physical parameters will be set here
  6516                              <1> 	; because, number of heads <= 16.
  6517                              <1> 	; (logical heads usually more than 16)
  6518                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6519                              <1> 	;	== INT 13h physical parameters
  6520                              <1> 
  6521                              <1> ;INIT_DRV:
  6522                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6523                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6524                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6525                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6526                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6527                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6528                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6529                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6530                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6531                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6532                              <1> ;	SUB	AX,AX
  6533                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6534                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6535                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6536                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6537                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6538                              <1> ;	CALL	CHECK_STATUS
  6539                              <1> ;INIT_EXIT:
  6540                              <1> ;	RETn
  6541                              <1> 
  6542                              <1> ; 04/01/2015
  6543                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6544                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6545                              <1> INIT_DRV:
  6546                              <1> 	;xor	ah,ah
  6547 000029AF 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6548 000029B1 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6549 000029B3 3825[946B0000]      <1>         cmp     [LBAMode], ah   ; 0
  6550 000029B9 7702                <1> 	ja	short idrv0
  6551 000029BB B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6552                              <1> idrv0:
  6553                              <1> 	; DL = drive number (0 based)
  6554 000029BD E8BB030000          <1> 	call	GET_VEC
  6555                              <1> 	;push	bx
  6556 000029C2 53                  <1> 	push	ebx ; 21/02/2015
  6557                              <1> 	;add	bx,ax
  6558 000029C3 01C3                <1> 	add	ebx,eax
  6559                              <1> 	;; 05/01/2015
  6560 000029C5 8A25[D8650000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6561                              <1> 	;;and 	ah,1 
  6562 000029CB C0E404              <1> 	shl	ah,4
  6563 000029CE 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6564                              <1> 	;mov	al,[es:bx]
  6565 000029D1 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6566 000029D3 FEC8                <1> 	dec	al	 ; last head number 
  6567                              <1> 	;and	al,0Fh
  6568 000029D5 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6569                              <1> 	;
  6570 000029D7 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6571 000029DB 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6572                              <1> 	;pop	bx
  6573 000029DE 5B                  <1> 	pop	ebx
  6574 000029DF 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6575 000029E1 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6576 000029E3 803D[946B0000]00    <1> 	cmp	byte [LBAMode],0
  6577 000029EA 7702                <1> 	ja	short idrv1
  6578 000029EC B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6579                              <1> idrv1:
  6580                              <1> 	;xor	ah,ah
  6581                              <1> 	;add	bx,ax
  6582 000029EE 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6583                              <1> 	;mov	al,[es:bx]
  6584                              <1> 			; sector number
  6585 000029F0 8A03                <1> 	mov	al,[ebx]
  6586 000029F2 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6587 000029F5 28C0                <1> 	sub	al,al
  6588 000029F7 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6589 000029FA E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6590 000029FF 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6591 00002A01 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6592 00002A06 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6593 00002A08 E8C3020000          <1> 	call	CHECK_STATUS
  6594                              <1> INIT_EXIT:
  6595 00002A0D C3                  <1> 	RETn
  6596                              <1> 
  6597                              <1> ;----------------------------------------
  6598                              <1> ;	READ LONG	     (AH = 0AH) :
  6599                              <1> ;----------------------------------------
  6600                              <1> 
  6601                              <1> RD_LONG:
  6602                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6603 00002A0E C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6604 00002A12 E9E0000000          <1>         JMP     COMMANDI
  6605                              <1> 
  6606                              <1> ;----------------------------------------
  6607                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6608                              <1> ;----------------------------------------
  6609                              <1> 
  6610                              <1> WR_LONG:
  6611                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6612 00002A17 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6613 00002A1B E92C010000          <1>         JMP     COMMANDO
  6614                              <1> 
  6615                              <1> ;----------------------------------------
  6616                              <1> ;	SEEK		     (AH = 0CH) :
  6617                              <1> ;----------------------------------------
  6618                              <1> 
  6619                              <1> DISK_SEEK:
  6620 00002A20 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6621 00002A24 E89A010000          <1> 	CALL	COMMAND
  6622 00002A29 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6623 00002A2B E80C020000          <1> 	CALL	_WAIT
  6624 00002A30 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6625 00002A32 E899020000          <1> 	CALL	CHECK_STATUS
  6626 00002A37 803D[7F6B0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6627 00002A3E 7507                <1> 	JNE	short DS_EXIT
  6628 00002A40 C605[7F6B0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6629                              <1> DS_EXIT:
  6630 00002A47 C3                  <1> 	RETn
  6631                              <1> 
  6632                              <1> ;----------------------------------------
  6633                              <1> ;	TEST DISK READY      (AH = 10H) :
  6634                              <1> ;----------------------------------------
  6635                              <1> 
  6636                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6637 00002A48 E82B020000          <1> 	CALL	NOT_BUSY
  6638 00002A4D 751C                <1> 	JNZ	short TR_EX
  6639 00002A4F 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6640 00002A52 668B15[D4650000]    <1> 	MOV	DX,[HF_PORT]
  6641 00002A59 80C206              <1> 	add	dl,6
  6642 00002A5C EE                  <1> 	OUT	DX,AL
  6643 00002A5D E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6644 00002A62 7507                <1> 	JNZ	short TR_EX
  6645 00002A64 C605[7F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6646                              <1> TR_EX:	
  6647 00002A6B C3                  <1> 	RETn
  6648                              <1> 
  6649                              <1> ;----------------------------------------
  6650                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6651                              <1> ;----------------------------------------
  6652                              <1> 
  6653                              <1> HDISK_RECAL:
  6654 00002A6C C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6655 00002A70 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6656 00002A75 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6657 00002A77 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6658 00002A7C 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6659 00002A7E E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6660 00002A83 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6661                              <1> RECAL_X:
  6662 00002A85 E846020000          <1> 	CALL	CHECK_STATUS
  6663 00002A8A 803D[7F6B0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6664 00002A91 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6665 00002A93 C605[7F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6666                              <1> RECAL_EXIT:
  6667 00002A9A 803D[7F6B0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6668 00002AA1 C3                  <1> 	RETn
  6669                              <1> 
  6670                              <1> ;----------------------------------------
  6671                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6672                              <1> ;----------------------------------------
  6673                              <1> 
  6674                              <1> CTLR_DIAGNOSTIC:
  6675 00002AA2 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6676 00002AA3 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6677                              <1> 	;AND	AL,0BFH
  6678 00002AA5 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6679                              <1> 	;JMP	$+2
  6680                              <1> 	IODELAY
  2101 00002AA7 EB00                <2>  jmp short $+2
  2102 00002AA9 EB00                <2>  jmp short $+2
  6681 00002AAB E6A1                <1> 	OUT	INTB01,AL
  6682                              <1> 	IODELAY
  2101 00002AAD EB00                <2>  jmp short $+2
  2102 00002AAF EB00                <2>  jmp short $+2
  6683 00002AB1 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6684 00002AB3 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6685                              <1> 	;JMP	$+2
  6686                              <1> 	IODELAY
  2101 00002AB5 EB00                <2>  jmp short $+2
  2102 00002AB7 EB00                <2>  jmp short $+2
  6687 00002AB9 E621                <1> 	OUT	INTA01,AL
  6688 00002ABB FB                  <1> 	STI
  6689 00002ABC E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6690 00002AC1 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6691                              <1> 	;MOV	DX, HF_PORT+7
  6692 00002AC3 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  6693 00002ACA 80C207              <1> 	add	dl, 7
  6694 00002ACD B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6695 00002ACF EE                  <1> 	OUT	DX,AL
  6696 00002AD0 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6697 00002AD5 B480                <1> 	MOV	AH,TIME_OUT
  6698 00002AD7 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6699                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6700 00002AD9 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  6701 00002AE0 FEC2                <1> 	inc	dl
  6702 00002AE2 EC                  <1> 	IN	AL,DX
  6703 00002AE3 A2[766B0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6704 00002AE8 B400                <1> 	MOV	AH,0
  6705 00002AEA 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6706 00002AEC 7402                <1> 	JE	SHORT CD_EXIT
  6707 00002AEE B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6708                              <1> CD_EXIT:
  6709 00002AF0 8825[7F6B0000]      <1> 	MOV	[DISK_STATUS1],AH
  6710 00002AF6 C3                  <1> 	RETn
  6711                              <1> 
  6712                              <1> ;----------------------------------------
  6713                              <1> ; COMMANDI				:
  6714                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6715                              <1> ;	NSECTOR RETURNS ZERO		:
  6716                              <1> ;----------------------------------------
  6717                              <1> COMMANDI:
  6718 00002AF7 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6719 00002AFC 724D                <1> 	JC	short CMD_ABORT
  6720                              <1> 	;MOV	DI,BX
  6721 00002AFE 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6722 00002B00 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6723 00002B05 7544                <1> 	JNZ	short CMD_ABORT
  6724                              <1> CMD_I1:
  6725 00002B07 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6726 00002B0C 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6727                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6728 00002B0E B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6729                              <1> 	;MOV	DX,HF_PORT
  6730 00002B13 668B15[D4650000]    <1> 	mov	dx,[HF_PORT]
  6731 00002B1A FA                  <1> 	CLI
  6732 00002B1B FC                  <1> 	CLD
  6733 00002B1C F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6734 00002B1F FB                  <1> 	STI
  6735 00002B20 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6736 00002B24 7419                <1> 	JZ	CMD_I3
  6737 00002B26 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6738 00002B2B 721E                <1> 	JC	short TM_OUT
  6739                              <1> 	;MOV	DX,HF_PORT
  6740 00002B2D 668B15[D4650000]    <1> 	mov	dx,[HF_PORT]
  6741                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6742 00002B34 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6743 00002B39 EC                  <1> CMD_I2: IN	AL,DX
  6744                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6745 00002B3A 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6746 00002B3C 47                  <1> 	INC	eDI
  6747 00002B3D E2FA                <1> 	LOOP	CMD_I2
  6748 00002B3F E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6749 00002B44 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6750 00002B46 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6751 00002B49 75BC                <1> 	JNZ	SHORT CMD_I1
  6752                              <1> CMD_ABORT:
  6753 00002B4B C3                  <1> TM_OUT: RETn
  6754                              <1> 
  6755                              <1> ;----------------------------------------
  6756                              <1> ; COMMANDO				:
  6757                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6758                              <1> ;	NSECTOR RETURNS ZERO		:
  6759                              <1> ;----------------------------------------
  6760                              <1> COMMANDO:
  6761 00002B4C E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6762 00002B51 72F8                <1> 	JC	short CMD_ABORT
  6763 00002B53 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6764 00002B55 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6765 00002B5A 75EF                <1> 	JNZ	short CMD_ABORT
  6766 00002B5C E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6767 00002B61 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6768                              <1> CMD_O1: ;PUSH	DS
  6769                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6770                              <1> 	;POP	DS
  6771                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6772                              <1> 	;MOV	DX,HF_PORT
  6773                              <1> 	; 01/02/2015
  6774 00002B63 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  6775                              <1> 	;push	es
  6776                              <1> 	;pop	ds
  6777                              <1> 	;mov	cx, 256
  6778 00002B6A B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6779 00002B6F FA                  <1> 	CLI
  6780 00002B70 FC                  <1> 	CLD
  6781 00002B71 F3666F              <1> 	REP	OUTSW
  6782 00002B74 FB                  <1> 	STI
  6783                              <1> 	;POP	DS			; RESTORE DS
  6784 00002B75 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6785 00002B79 7419                <1> 	JZ	short CMD_O3
  6786 00002B7B E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6787 00002B80 72C9                <1> 	JC	short TM_OUT
  6788                              <1> 	;MOV	DX,HF_PORT
  6789 00002B82 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  6790                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6791 00002B89 B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6792                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6793 00002B8E 8A06                <1> 	mov	al, [esi]
  6794 00002B90 EE                  <1> 	OUT	DX,AL
  6795 00002B91 46                  <1> 	INC	eSI
  6796 00002B92 E2FA                <1> 	LOOP	CMD_O2
  6797                              <1> CMD_O3:
  6798 00002B94 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6799 00002B99 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6800 00002B9B E830010000          <1> 	CALL	CHECK_STATUS
  6801 00002BA0 75A9                <1> 	JNZ	short CMD_ABORT
  6802 00002BA2 F605[756B0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6803 00002BA9 75B8                <1> 	JNZ	SHORT CMD_O1
  6804                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6805 00002BAB 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  6806                              <1> 	;add	dl, 2
  6807 00002BB2 FEC2                <1> 	inc	dl
  6808 00002BB4 FEC2                <1> 	inc	dl
  6809 00002BB6 EC                  <1> 	IN	AL,DX			;
  6810 00002BB7 A8FF                <1> 	TEST	AL,0FFH 		;
  6811 00002BB9 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6812 00002BBB C605[7F6B0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6813                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6814                              <1> CMD_O4:
  6815 00002BC2 C3                  <1> 	RETn
  6816                              <1> 
  6817                              <1> ;--------------------------------------------------------
  6818                              <1> ; COMMAND						:
  6819                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6820                              <1> ; OUTPUT						:
  6821                              <1> ;	BL = STATUS					:
  6822                              <1> ;	BH = ERROR REGISTER				:
  6823                              <1> ;--------------------------------------------------------
  6824                              <1> 
  6825                              <1> COMMAND:
  6826 00002BC3 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6827                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6828                              <1> COMMAND1:
  6829                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6830 00002BC4 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6831                              <1> 	;;POP	CX
  6832 00002BC9 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6833 00002BCB 803D[7F6B0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6834                              <1> 	;JZ	short CMD_TIMEOUT
  6835                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6836                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6837 00002BD2 7507                <1> 	jne	short COMMAND4
  6838                              <1> CMD_TIMEOUT:
  6839 00002BD4 C605[7F6B0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6840                              <1> COMMAND4:
  6841 00002BDB 5B                  <1> 	POP	eBX
  6842 00002BDC 803D[7F6B0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6843 00002BE3 C3                  <1> 	RETn
  6844                              <1> COMMAND2:
  6845 00002BE4 5B                  <1> 	POP	eBX
  6846 00002BE5 57                  <1> 	PUSH	eDI
  6847 00002BE6 C605[776B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6848 00002BED FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6849 00002BEE E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6850                              <1> 	;AND	AL,0BFH
  6851 00002BF0 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6852                              <1> 	;JMP	$+2
  6853                              <1> 	IODELAY
  2101 00002BF2 EB00                <2>  jmp short $+2
  2102 00002BF4 EB00                <2>  jmp short $+2
  6854 00002BF6 E6A1                <1> 	OUT	INTB01,AL
  6855 00002BF8 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6856 00002BFA 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6857                              <1> 	;JMP	$+2
  6858                              <1> 	IODELAY
  2101 00002BFC EB00                <2>  jmp short $+2
  2102 00002BFE EB00                <2>  jmp short $+2
  6859 00002C00 E621                <1> 	OUT	INTA01,AL
  6860 00002C02 FB                  <1> 	STI
  6861 00002C03 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6862                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6863 00002C05 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  6864 00002C0C FEC2                <1> 	inc	dl
  6865 00002C0E F605[816B0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6866 00002C15 7411                <1> 	JZ	short COMMAND3
  6867 00002C17 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6868 00002C1A 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6869 00002C1C 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6870 00002C1E 7208                <1> 	JB	short COMMAND3
  6871 00002C20 3C40                <1> 	CMP	AL,40H
  6872 00002C22 7704                <1> 	JA	short COMMAND3
  6873 00002C24 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6874                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6875                              <1> COMMAND3:
  6876 00002C28 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6877 00002C2C EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6878                              <1> 	IODELAY
  2101 00002C2D EB00                <2>  jmp short $+2
  2102 00002C2F EB00                <2>  jmp short $+2
  6879 00002C31 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6880 00002C32 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6881 00002C34 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6882 00002C38 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6883 00002C3A 5F                  <1> 	POP	eDI
  6884 00002C3B C3                  <1> 	RETn				; ZERO FLAG IS SET
  6885                              <1> 
  6886                              <1> ;CMD_TIMEOUT:
  6887                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6888                              <1> ;COMMAND4:
  6889                              <1> ;	POP	BX
  6890                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6891                              <1> ;	RETn
  6892                              <1> 
  6893                              <1> ;----------------------------------------
  6894                              <1> ;	WAIT FOR INTERRUPT		:
  6895                              <1> ;----------------------------------------
  6896                              <1> ;WAIT:
  6897                              <1> _WAIT:
  6898 00002C3C FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6899                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6900                              <1> 	;CLC
  6901                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6902                              <1> 	;INT	15H
  6903                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6904                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6905                              <1> 
  6906                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6907                              <1> 	;; 21/02/2015
  6908                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6909                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6910 00002C3D B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6911                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6912                              <1> ;-----	WAIT LOOP
  6913                              <1> 
  6914                              <1> WT1:	
  6915                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6916 00002C42 F605[776B0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6917                              <1> 	;LOOPZ	WT1
  6918 00002C49 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6919                              <1> 	;DEC	BL
  6920                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6921                              <1> 
  6922                              <1> WT1_hi:
  6923 00002C4B E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6924 00002C4D A810                <1> 	test	al, 10h			; transition on memory
  6925 00002C4F 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6926                              <1> WT1_lo:
  6927 00002C51 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6928 00002C53 A810                <1> 	test	al, 10h			
  6929 00002C55 74FA                <1> 	jz	short WT1_lo
  6930 00002C57 E2E9                <1> 	loop	WT1
  6931                              <1> 	;;or	bl, bl
  6932                              <1> 	;;jz	short WT2	
  6933                              <1> 	;;dec	bl
  6934                              <1> 	;;jmp	short WT1
  6935                              <1> 	;dec	bl
  6936                              <1> 	;jnz	short WT1	
  6937                              <1> 
  6938 00002C59 C605[7F6B0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6939 00002C60 EB0E                <1> 	JMP	SHORT WT4
  6940 00002C62 C605[7F6B0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6941 00002C69 C605[776B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6942 00002C70 803D[7F6B0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6943 00002C77 C3                  <1> 	RETn
  6944                              <1> 
  6945                              <1> ;----------------------------------------
  6946                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6947                              <1> ;----------------------------------------
  6948                              <1> NOT_BUSY:
  6949 00002C78 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6950                              <1> 	;PUSH	eBX
  6951                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6952 00002C79 668B15[D4650000]    <1> 	mov	DX, [HF_PORT]
  6953 00002C80 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6954                              <1> 	;MOV	BL,DELAY_1
  6955                              <1> 					; wait for 10 seconds
  6956                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6957                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6958                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6959 00002C83 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6960                              <1> 	;
  6961                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6962                              <1> NB1:	
  6963 00002C88 EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6964                              <1> 	;TEST	AL,ST_BUSY
  6965 00002C89 2480                <1> 	and	al, ST_BUSY
  6966                              <1> 	;LOOPNZ	NB1
  6967 00002C8B 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6968                              <1> 	;DEC	BL			
  6969                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6970                              <1> 
  6971 00002C8D E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  6972 00002C8F A810                <1> 	TEST	AL,010H			; transition on memory
  6973 00002C91 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  6974 00002C93 E461                <1> NB1_lo: IN	AL,SYS1
  6975 00002C95 A810                <1> 	TEST	AL,010H
  6976 00002C97 74FA                <1> 	JZ	short NB1_lo
  6977 00002C99 E2ED                <1> 	LOOP	NB1
  6978                              <1> 	;dec	bl
  6979                              <1> 	;jnz	short NB1
  6980                              <1> 	;
  6981                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6982                              <1> ;;	jb	short NB1
  6983                              <1> 	;
  6984                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  6985                              <1> 	;JMP	SHORT NB3
  6986 00002C9B B080                <1> 	mov	al, TIME_OUT
  6987                              <1> NB2:	
  6988                              <1> 	;MOV	byte [DISK_STATUS1],0
  6989                              <1> ;NB3:	
  6990                              <1> 	;POP	eBX
  6991 00002C9D A2[7F6B0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  6992                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6993 00002CA2 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  6994 00002CA4 C3                  <1> 	RETn
  6995                              <1> 
  6996                              <1> ;----------------------------------------
  6997                              <1> ;	WAIT FOR DATA REQUEST		:
  6998                              <1> ;----------------------------------------
  6999                              <1> WAIT_DRQ:
  7000                              <1> 	;MOV	CX,DELAY_3
  7001                              <1> 	;MOV	DX,HF_PORT+7
  7002 00002CA5 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  7003 00002CAC 80C207              <1> 	add	dl, 7
  7004                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7005                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7006                              <1> 					; (but it is written as 2000
  7007                              <1> 					; micro seconds in ATORGS.ASM file
  7008                              <1> 					; of Award Bios - 1999, D1A0622)
  7009 00002CAF B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7010 00002CB4 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7011 00002CB5 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7012 00002CB7 7516                <1> 	JNZ	short WQ_OK
  7013                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7014                              <1> WQ_hi:	
  7015 00002CB9 E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7016 00002CBB A810                <1> 	TEST	AL,010H			; transition on memory
  7017 00002CBD 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7018 00002CBF E461                <1> WQ_lo:  IN      AL,SYS1
  7019 00002CC1 A810                <1> 	TEST	AL,010H
  7020 00002CC3 74FA                <1> 	JZ	SHORT WQ_lo
  7021 00002CC5 E2ED                <1> 	LOOP	WQ_1
  7022                              <1> 
  7023 00002CC7 C605[7F6B0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7024 00002CCE F9                  <1> 	STC
  7025                              <1> WQ_OK:
  7026 00002CCF C3                  <1> 	RETn
  7027                              <1> ;WQ_OK:	;CLC
  7028                              <1> ;	RETn
  7029                              <1> 
  7030                              <1> ;----------------------------------------
  7031                              <1> ;	CHECK FIXED DISK STATUS 	:
  7032                              <1> ;----------------------------------------
  7033                              <1> CHECK_STATUS:
  7034 00002CD0 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7035 00002CD5 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7036 00002CD7 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7037 00002CD9 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7038 00002CDB E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7039                              <1> CHECK_S1:
  7040 00002CE0 803D[7F6B0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7041 00002CE7 C3                  <1> 	RETn
  7042                              <1> 
  7043                              <1> ;----------------------------------------
  7044                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7045                              <1> ;----------------------------------------
  7046                              <1> CHECK_ST:
  7047                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7048 00002CE8 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]
  7049 00002CEF 80C207              <1> 	add	dl, 7
  7050 00002CF2 EC                  <1> 	IN	AL,DX
  7051 00002CF3 A2[756B0000]        <1> 	MOV	[HF_STATUS],AL
  7052 00002CF8 B400                <1> 	MOV	AH,0
  7053 00002CFA A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7054 00002CFC 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7055 00002CFE B4CC                <1> 	MOV	AH,WRITE_FAULT
  7056 00002D00 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7057 00002D02 7514                <1> 	JNZ	short CKST_EXIT
  7058 00002D04 B4AA                <1> 	MOV	AH,NOT_RDY
  7059 00002D06 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7060 00002D08 740E                <1> 	JZ	short CKST_EXIT
  7061 00002D0A B440                <1> 	MOV	AH,BAD_SEEK
  7062 00002D0C A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7063 00002D0E 7408                <1> 	JZ	short CKST_EXIT
  7064 00002D10 B411                <1> 	MOV	AH,DATA_CORRECTED
  7065 00002D12 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7066 00002D14 7502                <1> 	JNZ	short CKST_EXIT
  7067 00002D16 B400                <1> 	MOV	AH,0
  7068                              <1> CKST_EXIT:
  7069 00002D18 8825[7F6B0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7070 00002D1E 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7071 00002D21 7403                <1> 	JZ	short CKST_EX1
  7072 00002D23 80FC00              <1> 	CMP	AH,0
  7073                              <1> CKST_EX1:
  7074 00002D26 C3                  <1> 	RETn
  7075                              <1> 
  7076                              <1> ;----------------------------------------
  7077                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7078                              <1> ;----------------------------------------
  7079                              <1> CHECK_ER:
  7080                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7081 00002D27 668B15[D4650000]    <1> 	mov	dx, [HF_PORT]		;
  7082 00002D2E FEC2                <1> 	inc	dl
  7083 00002D30 EC                  <1> 	IN	AL,DX
  7084 00002D31 A2[766B0000]        <1> 	MOV	[HF_ERROR],AL
  7085 00002D36 53                  <1> 	PUSH	eBX ; 21/02/2015
  7086 00002D37 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7087 00002D3C D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7088 00002D3E 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7089 00002D40 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7090 00002D42 BB[C8650000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7091 00002D47 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7092                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7093                              <1> 	;mov	ah, [bx]
  7094 00002D49 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7095 00002D4B 8825[7F6B0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7096 00002D51 5B                  <1> 	POP	eBX
  7097 00002D52 80FC00              <1> 	CMP	AH,0
  7098 00002D55 C3                  <1> 	RETn
  7099                              <1> 
  7100                              <1> ;--------------------------------------------------------
  7101                              <1> ; CHECK_DMA						:
  7102                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7103                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7104                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7105                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7106                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7107                              <1> ;  -ERROR OTHERWISE					:
  7108                              <1> ;--------------------------------------------------------
  7109                              <1> CHECK_DMA:
  7110                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7111                              <1> 	; 24/12/2021
  7112 00002D56 50                  <1> 	push	eax
  7113 00002D57 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7114 00002D5B F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7115 00002D5F 7404                <1> 	JZ	short CKD1
  7116 00002D61 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7117 00002D65 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7118 00002D68 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7119 00002D6A 7207                <1> 	JB	short CKDERR		; TOO MANY
  7120 00002D6C 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7121 00002D6E 7203                <1> 	JB	short CKDERR		; ERROR
  7122 00002D70 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7123                              <1> 	;POP	AX
  7124                              <1> 	; 24/12/2021
  7125 00002D71 58                  <1> 	pop	eax
  7126 00002D72 C3                  <1> 	RETn				; NORMAL RETURN
  7127 00002D73 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7128 00002D74 C605[7F6B0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7129                              <1> 	;POP	AX
  7130                              <1> 	; 24/12/2021
  7131 00002D7B 58                  <1> 	pop	eax	
  7132 00002D7C C3                  <1> 	RETn
  7133                              <1> 
  7134                              <1> ;----------------------------------------
  7135                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7136                              <1> ;----------------------------------------
  7137                              <1> 					
  7138                              <1> ; INPUT -> DL = 0 based drive number
  7139                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7140                              <1> 
  7141                              <1> GET_VEC:
  7142                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7143                              <1> 	;MOV	ES,AX
  7144                              <1> 	;TEST	DL,1
  7145                              <1> 	;JZ	short GV_0
  7146                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7147                              <1> ;	JMP	SHORT GV_EXIT
  7148                              <1> ;GV_0:
  7149                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7150                              <1> ;
  7151                              <1> 	;xor	bh, bh
  7152 00002D7D 31DB                <1> 	xor	ebx, ebx
  7153 00002D7F 88D3                <1> 	mov	bl, dl
  7154                              <1> 	;;02/01/2015
  7155                              <1> 	;;shl	bl, 1			; port address offset
  7156                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7157                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7158 00002D81 C0E302              <1> 	shl	bl, 2	;;
  7159                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7160 00002D84 81C3[846B0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7161                              <1> 	;push	word [bx+2]		; dpt segment
  7162                              <1> 	;pop	es
  7163                              <1> 	;mov	bx, [bx]		; dpt offset
  7164 00002D8A 8B1B                <1> 	mov	ebx, [ebx]		
  7165                              <1> ;GV_EXIT:
  7166 00002D8C C3                  <1> 	RETn
  7167                              <1> 
  7168                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7169                              <1> hdc1_int: ; 21/02/2015
  7170                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7171                              <1> ;								:
  7172                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7173                              <1> ;								:
  7174                              <1> ;----------------------------------------------------------------
  7175                              <1> 
  7176                              <1> ; 22/12/2014
  7177                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7178                              <1> ;	 '11/15/85'
  7179                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7180                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7181                              <1> 
  7182                              <1> ;int_76h:
  7183                              <1> HD_INT:
  7184                              <1> 	;push	ax
  7185                              <1> 	; 24/12/2021
  7186 00002D8D 50                  <1> 	push	eax
  7187 00002D8E 1E                  <1> 	push	ds
  7188                              <1> 	;CALL	DDS
  7189                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7190 00002D8F 66B81000            <1> 	mov	ax, KDATA
  7191 00002D93 8ED8                <1> 	mov 	ds, ax
  7192                              <1> 	;
  7193                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7194                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7195 00002D95 C605[776B0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7196                              <1> 	;
  7197                              <1> 	;push	dx
  7198                              <1> 	; 24/12/2021
  7199 00002D9C 52                  <1> 	push	edx
  7200 00002D9D 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7201                              <1> 					; Clear Controller
  7202                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7203 00002DA1 EC                  <1> 	in	al, dx			;
  7204                              <1> 	;pop	dx
  7205                              <1> 	; 24/12/2021
  7206 00002DA2 5A                  <1> 	pop	edx
  7207                              <1> 	NEWIODELAY
  2106 00002DA3 E6EB                <2>  out 0EBh,al
  7208                              <1> 	;
  7209 00002DA5 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7210 00002DA7 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7211                              <1> 	;JMP	$+2			; WAIT
  7212                              <1> 	NEWIODELAY
  2106 00002DA9 E6EB                <2>  out 0EBh,al
  7213 00002DAB E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7214 00002DAD 1F                  <1> 	pop	ds
  7215                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7216                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7217                              <1> 	;INT	15H			;  INTERRUPT
  7218                              <1> irq15_iret: ; 25/02/2015
  7219                              <1> 	;pop	ax
  7220                              <1> 	; 24/12/2021
  7221 00002DAE 58                  <1> 	pop	eax
  7222 00002DAF CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7223                              <1> 
  7224                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7225                              <1> hdc2_int: ; 21/02/2015
  7226                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7227                              <1> ;								:
  7228                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7229                              <1> ;								:
  7230                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7231                              <1> 
  7232                              <1> ;int_77h:
  7233                              <1> HD1_INT:
  7234                              <1> 	;push	ax
  7235                              <1> 	; 24/12/2021
  7236 00002DB0 50                  <1> 	push	eax
  7237                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7238                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7239 00002DB1 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7240 00002DB3 E6A0                <1> 	out	0A0h, al
  7241 00002DB5 EB00                <1>         jmp short $+2
  7242 00002DB7 EB00                <1> 	jmp short $+2
  7243 00002DB9 E4A0                <1> 	in	al, 0A0h
  7244 00002DBB 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7245 00002DBD 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7246                              <1> 	;
  7247 00002DBF 1E                  <1> 	push	ds
  7248                              <1> 	;CALL	DDS
  7249                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7250 00002DC0 66B81000            <1> 	mov	ax, KDATA
  7251 00002DC4 8ED8                <1> 	mov 	ds, ax
  7252                              <1> 	;
  7253                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7254                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7255 00002DC6 800D[776B0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7256                              <1> 	;
  7257                              <1> 	;push	dx
  7258                              <1> 	; 24/12/2021
  7259 00002DCD 52                  <1> 	push	edx
  7260 00002DCE 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7261                              <1> 					; Clear Controller (Award BIOS 1999)
  7262 00002DD2 EBCD                <1> 	jmp	short Clear_IRQ1415
  7263                              <1> 
  7264                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7265                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7266                              <1> 
  7267                              <1> ;////////////////////////////////////////////////////////////////////
  7268                              <1> ;; END OF DISK I/O SYTEM ///
  2043                                  %include 'memory.inc'  ; 09/03/2015
  2044                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2045                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.18) - MEMORY.INC
  2046                              <1> ; Last Modification: 03/02/2022 [ 31/12/2021 (Retro UNIX 386 v1.1) ]
  2047                              <1> ;
  2048                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2049                              <1> 
  2050                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.1 - MEMORY.INC (31/12/2021)
  2051                              <1> 
  2052                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2053                              <1> 
  2054                              <1> ;;04/11/2014 (unix386.s)	
  2055                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2056                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2057                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2058                              <1> ;;
  2059                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2060                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2061                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2062                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2063                              <1> 
  2064                              <1> ; 27/04/2015
  2065                              <1> ; 09/03/2015
  2066                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2067                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2068                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2069                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2070                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2071                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2072                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2073                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2074                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2075                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2076                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2077                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2078                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2079                              <1> SWP_DISK_READ_ERR 	   equ 40
  2080                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2081                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2082                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2083                              <1> SWP_DISK_WRITE_ERR         equ 44
  2084                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2085                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2086                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2087                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2088                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2089                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2090                              <1> 					; (Indicates that the page is not allocated
  2091                              <1> 					; for the process, it is a shared or system
  2092                              <1>                                         ; page, it must not be deallocated!)
  2093                              <1> ; 14/12/2020
  2094                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2095                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2096                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2097                              <1> 				; (Out of memory allocation table)	
  2098                              <1> ;
  2099                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2100                              <1> ;;
  2101                              <1> ;; 10/10/2014
  2102                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2103                              <1> ;;
  2104                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2105                              <1> ;;	(virtual address = physical address)
  2106                              <1> ;; KERNEL PAGE TABLES:
  2107                              <1> ;;	Kernel page directory and all page tables are
  2108                              <1> ;;	on memory as initialized, as equal to physical memory
  2109                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2110                              <1> ;;
  2111                              <1> ;;	what for: User pages may be swapped out, when accessing
  2112                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2113                              <1> ;;	kernel would have to swap it in! But it is also may be
  2114                              <1> ;;	in use by a user process. (In system/kernel mode
  2115                              <1> ;;	kernel can access all memory pages even if they are
  2116                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2117                              <1> ;;	cause conflicts.) 
  2118                              <1> ;;	
  2119                              <1> ;;	As result of these conditions,
  2120                              <1> ;;	all kernel pages must be initialized as equal to 
  2121                              <1> ;;	physical layout for preventing page faults. 
  2122                              <1> ;;	Also, calling "allocate page" procedure after
  2123                              <1> ;;	a page fault can cause another page fault (double fault)
  2124                              <1> ;;	if all kernel page tables would not be initialized.
  2125                              <1> ;;
  2126                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2127                              <1> ;;	memory allocation table. (double word aligned)
  2128                              <1> ;;
  2129                              <1> ;;	[next_page] = first/next free space to be searched
  2130                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2131                              <1> ;;
  2132                              <1> ;;	[last_page] = End of memory (users space), as offset
  2133                              <1> ;;	to memory allocation table. (double word aligned)
  2134                              <1> ;;
  2135                              <1> ;; USER PAGE TABLES:
  2136                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2137                              <1> ;;		'ready only' marked copies of the 
  2138                              <1> ;;		parent process's page table entries (for
  2139                              <1> ;;		same physical memory).
  2140                              <1> ;;		(A page will be copied to a new page after
  2141                              <1> ;;		 if it causes R/W page fault.)
  2142                              <1> ;;
  2143                              <1> ;;	Every user process has own (different)
  2144                              <1> ;;	page directory and page tables.	
  2145                              <1> ;;
  2146                              <1> ;;	Code starts at virtual address 0, always.
  2147                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2148                              <1> ;;	(Programs can be written/developed as simple
  2149                              <1> ;;	 flat memory programs.)
  2150                              <1> ;;
  2151                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2152                              <1> ;;	Memory page will be allocated by kernel only 
  2153                              <1> ;;		(in kernel/system mode only).
  2154                              <1> ;;	* After a
  2155                              <1> ;;	  - 'not present' page fault
  2156                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2157                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2158                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2159                              <1> ;;	  request by running process.
  2160                              <1> ;;	* While creating a process, allocating a new buffer,
  2161                              <1> ;;	  new page tables etc.
  2162                              <1> ;;
  2163                              <1> ;;	At first,
  2164                              <1> ;;	- 'allocate page' procedure will be called;
  2165                              <1> ;,	   if it will return with a valid (>0) physical address
  2166                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2167                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2168                              <1> ;;	- 'allocate page' will be called for allocating page
  2169                              <1> ;;	   directory, page table and running space (data/code).
  2170                              <1> ;;	- every successful 'allocate page' call will decrease
  2171                              <1> ;;	  'free_pages' count (pointer).
  2172                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2173                              <1> ;;	  if 'free_pages' points to a ZERO.
  2174                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2175                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2176                              <1> ;;	  error except errors caused by attribute conflicts.
  2177                              <1> ;;	 (swapper functions)	 
  2178                              <1> ;;					
  2179                              <1> ;;	At second,
  2180                              <1> ;;	- page directory entry will be updated then page table
  2181                              <1> ;;	  entry will be updated.		
  2182                              <1> ;;
  2183                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2184                              <1> ;;	- M.A.T. has a size according to available memory as
  2185                              <1> ;;	  follows:
  2186                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2187                              <1> ;;		  - a bit with value of 0 means allocated page
  2188                              <1> ;;		  - a bit with value of 1 means a free page
  2189                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2190                              <1> ;;	  depending on M.A.T.
  2191                              <1> ;;		(NOTE: Free page count will not be checked
  2192                              <1> ;;		again -on M.A.T.- after initialization. 
  2193                              <1> ;;		Kernel will trust on initial count.)
  2194                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2195                              <1> ;;	  and it will be increased by deallocation procedures.
  2196                              <1> ;;	
  2197                              <1> ;;	- Available memory will be calculated during
  2198                              <1> ;;	  the kernel's initialization stage (in real mode).
  2199                              <1> ;;	  Memory allocation table and kernel page tables 
  2200                              <1> ;;	  will be formatted/sized as result of available
  2201                              <1> ;;	  memory calculation before paging is enabled.
  2202                              <1> ;;
  2203                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2204                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2205                              <1> ;;	- Memory allocation for kernel page directory size 
  2206                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2207                              <1> ;;	  for page tables)
  2208                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2209                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2210                              <1> ;;	- User (available) space will be started 
  2211                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2212                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2213                              <1> ;;	  memory allocation table and kernel's page directory
  2214                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2215                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2216                              <1> ;; 	  for buffers.
  2217                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2218                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2219                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2220                              <1> ;;
  2221                              <1> ;; For 1GB Available Memory:
  2222                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2223                              <1> ;;	- Memory allocation for kernel page directory size 
  2224                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2225                              <1> ;;	  for page tables)
  2226                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2227                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2228                              <1> ;;	- User (available) space will be started 
  2229                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2230                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2231                              <1> ;;	  memory allocation table and kernel's page directory
  2232                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2233                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2234                              <1> ;; 	  for buffers.
  2235                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2236                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2237                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2238                              <1> ;;
  2239                              <1> ;;
  2240                              <1> 
  2241                              <1> ;;************************************************************************************
  2242                              <1> ;; 
  2243                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2244                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2245                              <1> 
  2246                              <1> ;; Main factor: "sys fork" system call 
  2247                              <1> ;;	
  2248                              <1> ;; 		FORK
  2249                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2250                              <1> ;;  writable pages ---->|
  2251                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2252                              <1> ;; 
  2253                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2254                              <1> ;; 
  2255                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2256                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2257                              <1> ;;       -while R/W bit is 0-. 
  2258                              <1> ;; 
  2259                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2260                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2261                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2262                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2263                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2264                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2265                              <1> ;; 
  2266                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2267                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2268                              <1> ;;   Parent's PTE attributes are not changed.
  2269                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2270                              <1> ;;    destroy/mix previous fork result).
  2271                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2272                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2273                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2274                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2275                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2276                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2277                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2278                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2279                              <1> ;; 
  2280                              <1> ;; !? WHAT FOR (duplication after duplication):
  2281                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2282                              <1> ;; program/executable code continues from specified location as child process, 
  2283                              <1> ;; returns back previous code location as parent process, every child after 
  2284                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2285                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2286                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2287                              <1> ;; was copied to child's process segment (all of code and data) according to
  2288                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2289                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2290                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2291                              <1> ;; (complete running image of parent process) to the child process; 
  2292                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2293                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2294                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2295                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2296                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2297                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2298                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2299                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2300                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2301                              <1> ;; for sharing same read only pages between parent and child processes.
  2302                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2303                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2304                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2305                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2306                              <1> ;; -deallocation problem-.
  2307                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2308                              <1> ;; 
  2309                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2310                              <1> ;; # Page fault handler will do those:
  2311                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2312                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2313                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2314                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2315                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2316                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2317                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2318                              <1> ;;     to child process.)	
  2319                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2320                              <1> ;; # Page fault handler will do those:
  2321                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2322                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2323                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2324                              <1> ;;     address or not. 
  2325                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2326                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2327                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2328                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2329                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2330                              <1> ;; 
  2331                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2332                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2333                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2334                              <1> ;;       duplication method details, it is not possible multiple child processes
  2335                              <1> ;;       were using same page with duplicated PTEs.
  2336                              <1> ;; 
  2337                              <1> ;;************************************************************************************   
  2338                              <1> 
  2339                              <1> ;; 08/10/2014
  2340                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2341                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2342                              <1> 
  2343                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2344                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2345                              <1> ;; (25/08/2014, Revision: 5057) file 
  2346                              <1> ;; by KolibriOS Team (2004-2012)
  2347                              <1> 
  2348                              <1> allocate_page:
  2349                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2350                              <1> 	; 01/07/2015
  2351                              <1> 	; 05/05/2015
  2352                              <1> 	; 30/04/2015
  2353                              <1> 	; 16/10/2014
  2354                              <1> 	; 08/10/2014
  2355                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2356                              <1> 	;
  2357                              <1> 	; INPUT -> none
  2358                              <1> 	;
  2359                              <1> 	; OUTPUT ->
  2360                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2361                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2362                              <1> 	;
  2363                              <1> 	;	CF = 1 and EAX = 0 
  2364                              <1> 	; 		   if there is not a free page to be allocated	
  2365                              <1> 	;
  2366                              <1> 	; Modified Registers -> none (except EAX)
  2367                              <1> 	;
  2368 00002DD4 A1[F06A0000]        <1> 	mov	eax, [free_pages]
  2369 00002DD9 21C0                <1> 	and	eax, eax
  2370 00002DDB 7438                <1> 	jz	short out_of_memory
  2371                              <1> 	;
  2372 00002DDD 53                  <1> 	push	ebx
  2373 00002DDE 51                  <1> 	push	ecx
  2374                              <1> 	;
  2375 00002DDF BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2376 00002DE4 89D9                <1> 	mov	ecx, ebx
  2377                              <1>  				     ; NOTE: 32 (first_page) is initial
  2378                              <1> 				     ; value of [next_page].
  2379                              <1> 				     ; It points to the first available
  2380                              <1> 				     ; page block for users (ring 3) ...	
  2381                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2382                              <1> 				     ; (at the of the first 4 MB)		
  2383 00002DE6 031D[F46A0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2384                              <1> 				 ; next_free_page >> 5
  2385 00002DEC 030D[F86A0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2386                              <1> 				 ; (total_pages - 1) >> 5
  2387                              <1> al_p_scan:
  2388 00002DF2 39CB                <1> 	cmp	ebx, ecx
  2389 00002DF4 770A                <1> 	ja	short al_p_notfound
  2390                              <1> 	;
  2391                              <1> 	; 01/07/2015
  2392                              <1> 	; AMD64 Architecture Programmers Manual
  2393                              <1> 	; Volume 3:
  2394                              <1> 	; General-Purpose and System Instructions
  2395                              <1> 	;
  2396                              <1> 	; BSF - Bit Scan Forward
  2397                              <1> 	;
  2398                              <1> 	;   Searches the value in a register or a memory location
  2399                              <1> 	;   (second operand) for the least-significant set bit. 
  2400                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2401                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2402                              <1> 	;   register (first operand). If the second operand contains 0, 
  2403                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2404                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2405                              <1> 	;   of the searched value
  2406                              <1> 	;
  2407 00002DF6 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2408                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2409                              <1> 			   ; loads the destination with an index to
  2410                              <1> 			   ; first set bit. (0 -> 31) 
  2411                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2412 00002DF9 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2413                              <1> 			 ;
  2414                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2415                              <1> 			 ;	  with value of 1 means 
  2416                              <1> 			 ;	  the corresponding page is free 
  2417                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2418 00002DFB 83C304              <1> 	add	ebx, 4
  2419                              <1> 			 ; We return back for searching next page block
  2420                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2421                              <1> 			 ;	 we always will find at least 1 free page here.
  2422 00002DFE EBF2                <1>         jmp     short al_p_scan
  2423                              <1> 	;
  2424                              <1> al_p_notfound:
  2425 00002E00 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2426 00002E06 890D[F46A0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2427                              <1> 				 ; (deallocate_page procedure will change it)
  2428 00002E0C 31C0                <1> 	xor	eax, eax
  2429 00002E0E A3[F06A0000]        <1> 	mov	[free_pages], eax ; 0
  2430 00002E13 59                  <1> 	pop	ecx
  2431 00002E14 5B                  <1> 	pop	ebx
  2432                              <1> 	;
  2433                              <1> ; 24/12/2021
  2434                              <1> ; ('swap_out' procedure call is disabled)
  2435                              <1> 
  2436                              <1> out_of_memory:
  2437                              <1> ;	call	swap_out
  2438                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2439                              <1> ;	;
  2440                              <1> ;	sub 	eax, eax ; 0
  2441 00002E15 F9                  <1> 	stc
  2442 00002E16 C3                  <1> 	retn
  2443                              <1> 
  2444                              <1> al_p_found:
  2445 00002E17 89D9                <1> 	mov	ecx, ebx
  2446 00002E19 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2447 00002E1F 890D[F46A0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2448                              <1> 				 ; address/offset (to the next)
  2449 00002E25 FF0D[F06A0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2450                              <1> 	;
  2451 00002E2B 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2452                              <1> 				 ; is copied into the Carry Flag and then cleared
  2453                              <1> 				 ; in the destination.
  2454                              <1> 				 ;
  2455                              <1> 				 ; Reset the bit which is corresponding to the 
  2456                              <1> 				 ; (just) allocated page.
  2457                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2458 00002E2E C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2459 00002E31 01C8                <1> 	add	eax, ecx	 ; = page number
  2460 00002E33 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2461                              <1> 	; EAX = physical address of memory page
  2462                              <1> 	;
  2463                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2464                              <1> 	;       according to this EAX value...
  2465 00002E36 59                  <1> 	pop	ecx
  2466 00002E37 5B                  <1> 	pop	ebx
  2467                              <1> al_p_ok:
  2468 00002E38 C3                  <1> 	retn
  2469                              <1> 
  2470                              <1> make_page_dir:
  2471                              <1> 	; 18/04/2015
  2472                              <1> 	; 12/04/2015
  2473                              <1> 	; 23/10/2014
  2474                              <1> 	; 16/10/2014
  2475                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2476                              <1> 	;
  2477                              <1> 	; INPUT ->
  2478                              <1> 	;	none
  2479                              <1> 	; OUTPUT ->
  2480                              <1> 	;	(EAX = 0)
  2481                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2482                              <1> 	;	cf = 0 ->
  2483                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2484                              <1> 	;		  process/user.
  2485                              <1> 	;
  2486                              <1> 	; Modified Registers -> EAX
  2487                              <1> 	;
  2488 00002E39 E896FFFFFF          <1> 	call	allocate_page
  2489 00002E3E 7216                <1> 	jc	short mkpd_error
  2490                              <1> 	;
  2491 00002E40 A3[FF6E0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2492                              <1> 				  ; (Physical address)
  2493                              <1> clear_page:
  2494                              <1> 	; 18/04/2015
  2495                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2496                              <1> 	;
  2497                              <1> 	; INPUT ->
  2498                              <1> 	;	EAX = physical address of the page
  2499                              <1> 	; OUTPUT ->
  2500                              <1> 	;	all bytes of the page will be cleared
  2501                              <1> 	;
  2502                              <1> 	; Modified Registers -> none
  2503                              <1> 	;
  2504 00002E45 57                  <1> 	push	edi
  2505 00002E46 51                  <1> 	push	ecx
  2506 00002E47 50                  <1> 	push	eax
  2507 00002E48 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2508 00002E4D 89C7                <1> 	mov	edi, eax
  2509 00002E4F 31C0                <1> 	xor	eax, eax
  2510 00002E51 F3AB                <1> 	rep	stosd
  2511 00002E53 58                  <1> 	pop	eax
  2512 00002E54 59                  <1> 	pop	ecx
  2513 00002E55 5F                  <1> 	pop	edi
  2514                              <1> mkpd_error:
  2515                              <1> mkpt_error:
  2516 00002E56 C3                  <1> 	retn
  2517                              <1> 
  2518                              <1> make_page_table:
  2519                              <1> 	; 23/06/2015
  2520                              <1> 	; 18/04/2015
  2521                              <1> 	; 12/04/2015
  2522                              <1> 	; 16/10/2014
  2523                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2524                              <1> 	;
  2525                              <1> 	; INPUT ->
  2526                              <1> 	;	EBX = virtual (linear) address
  2527                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2528                              <1> 	;	      (higher 20 bits must be ZERO)
  2529                              <1> 	;	      (bit 0 must be 1)	 
  2530                              <1> 	;	u.pgdir = page directory (physical) address
  2531                              <1> 	; OUTPUT ->
  2532                              <1> 	;	EDX = Page directory entry address
  2533                              <1> 	;	EAX = Page table address
  2534                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2535                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2536                              <1> 	;
  2537                              <1> 	; Modified Registers -> EAX, EDX
  2538                              <1> 	;
  2539 00002E57 E878FFFFFF          <1> 	call	allocate_page
  2540 00002E5C 72F8                <1> 	jc	short mkpt_error
  2541 00002E5E E811000000          <1> 	call	set_pde	
  2542 00002E63 EBE0                <1> 	jmp	short clear_page
  2543                              <1> 
  2544                              <1> make_page:
  2545                              <1> 	; 24/07/2015
  2546                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2547                              <1> 	;
  2548                              <1> 	; INPUT ->
  2549                              <1> 	;	EBX = virtual (linear) address
  2550                              <1> 	;	ECX = page attributes (lower 12 bits)
  2551                              <1> 	;	      (higher 20 bits must be ZERO)
  2552                              <1> 	;	      (bit 0 must be 1)	 
  2553                              <1> 	;	u.pgdir = page directory (physical) address
  2554                              <1> 	; OUTPUT ->
  2555                              <1> 	;	EBX = Virtual address
  2556                              <1> 	;	(EDX = PTE value)
  2557                              <1> 	;	EAX = Physical address
  2558                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2559                              <1> 	;
  2560                              <1> 	; Modified Registers -> EAX, EDX
  2561                              <1> 	;
  2562 00002E65 E86AFFFFFF          <1> 	call	allocate_page
  2563 00002E6A 7207                <1> 	jc	short mkp_err
  2564 00002E6C E821000000          <1> 	call	set_pte	
  2565 00002E71 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2566                              <1> mkp_err:
  2567 00002E73 C3                  <1> 	retn
  2568                              <1> 
  2569                              <1> set_pde:	; Set page directory entry (PDE)
  2570                              <1> 	; 20/07/2015
  2571                              <1> 	; 18/04/2015
  2572                              <1> 	; 12/04/2015
  2573                              <1> 	; 23/10/2014
  2574                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2575                              <1> 	;
  2576                              <1> 	; INPUT ->
  2577                              <1> 	;	EAX = physical address
  2578                              <1> 	;	      (use present value if EAX = 0)
  2579                              <1> 	;	EBX = virtual (linear) address
  2580                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2581                              <1> 	;	      (higher 20 bits must be ZERO)
  2582                              <1> 	;	      (bit 0 must be 1)	 
  2583                              <1> 	;	u.pgdir = page directory (physical) address
  2584                              <1> 	; OUTPUT ->
  2585                              <1> 	;	EDX = PDE address
  2586                              <1> 	;	EAX = page table address (physical)
  2587                              <1> 	;	;(CF=1 -> Invalid page address)
  2588                              <1> 	;
  2589                              <1> 	; Modified Registers -> EDX
  2590                              <1> 	;
  2591 00002E74 89DA                <1> 	mov	edx, ebx
  2592 00002E76 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2593 00002E79 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2594 00002E7C 0315[FF6E0000]      <1> 	add	edx, [u.pgdir]
  2595                              <1> 	;
  2596 00002E82 21C0                <1> 	and	eax, eax
  2597 00002E84 7506                <1> 	jnz	short spde_1
  2598                              <1> 	;
  2599 00002E86 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2600                              <1> 	;test	al, 1
  2601                              <1> 	;jz	short spde_2
  2602 00002E88 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2603                              <1> spde_1:
  2604                              <1> 	;and	cx, 0FFFh
  2605 00002E8C 8902                <1> 	mov	[edx], eax
  2606 00002E8E 66090A              <1> 	or	[edx], cx
  2607 00002E91 C3                  <1> 	retn
  2608                              <1> ;spde_2: ; error
  2609                              <1> ;	stc
  2610                              <1> ;	retn
  2611                              <1> 
  2612                              <1> set_pte:	; Set page table entry (PTE)
  2613                              <1> 	; 24/07/2015
  2614                              <1> 	; 20/07/2015
  2615                              <1> 	; 23/06/2015
  2616                              <1> 	; 18/04/2015
  2617                              <1> 	; 12/04/2015
  2618                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2619                              <1> 	;
  2620                              <1> 	; INPUT ->
  2621                              <1> 	;	EAX = physical page address
  2622                              <1> 	;	      (use present value if EAX = 0)
  2623                              <1> 	;	EBX = virtual (linear) address
  2624                              <1> 	;	ECX = page attributes (lower 12 bits)
  2625                              <1> 	;	      (higher 20 bits must be ZERO)
  2626                              <1> 	;	      (bit 0 must be 1)	 
  2627                              <1> 	;	u.pgdir = page directory (physical) address
  2628                              <1> 	; OUTPUT ->
  2629                              <1> 	;	EAX = physical page address
  2630                              <1> 	;	(EDX = PTE value)
  2631                              <1> 	;	EBX = virtual address
  2632                              <1> 	;
  2633                              <1> 	;	CF = 1 -> error
  2634                              <1> 	;
  2635                              <1> 	; Modified Registers -> EAX, EDX
  2636                              <1> 	;
  2637 00002E92 50                  <1> 	push	eax
  2638 00002E93 A1[FF6E0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2639 00002E98 E837000000          <1> 	call 	get_pde
  2640                              <1> 		; EDX = PDE address
  2641                              <1> 		; EAX = PDE value
  2642 00002E9D 5A                  <1> 	pop	edx ; physical page address
  2643 00002E9E 722A                <1> 	jc	short spte_err ; PDE not present
  2644                              <1> 	;
  2645 00002EA0 53                  <1> 	push	ebx ; 24/07/2015
  2646 00002EA1 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2647                              <1> 			    ; EDX = PT address (physical)	
  2648 00002EA5 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2649 00002EA8 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2650                              <1> 			 ; clear higher 10 bits (PD bits)
  2651 00002EAE C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2652 00002EB1 01C3                <1> 	add	ebx, eax
  2653                              <1> 	;
  2654 00002EB3 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2655 00002EB5 A801                <1> 	test	al, 1
  2656 00002EB7 740C                <1> 	jz	short spte_0
  2657 00002EB9 09D2                <1> 	or	edx, edx
  2658 00002EBB 750F                <1> 	jnz	short spte_1
  2659 00002EBD 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2660 00002EC1 89C2                <1> 	mov	edx, eax
  2661 00002EC3 EB09                <1> 	jmp	short spte_2	
  2662                              <1> spte_0:
  2663                              <1> 	; If this PTE contains a swap (disk) address,
  2664                              <1> 	; it can be updated by using 'swap_in' procedure
  2665                              <1> 	; only!
  2666 00002EC5 21C0                <1> 	and	eax, eax
  2667 00002EC7 7403                <1> 	jz	short spte_1
  2668                              <1> 	; 24/07/2015
  2669                              <1> 	; swapped page ! (on disk)
  2670 00002EC9 5B                  <1> 	pop	ebx
  2671                              <1> spte_err:
  2672 00002ECA F9                  <1> 	stc
  2673 00002ECB C3                  <1> 	retn
  2674                              <1> spte_1: 
  2675 00002ECC 89D0                <1> 	mov	eax, edx
  2676                              <1> spte_2:
  2677 00002ECE 09CA                <1> 	or	edx, ecx
  2678                              <1> 	; 23/06/2015
  2679 00002ED0 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2680                              <1> 	; 24/07/2015
  2681 00002ED2 5B                  <1> 	pop	ebx
  2682 00002ED3 C3                  <1> 	retn
  2683                              <1> 
  2684                              <1> get_pde:	; Get present value of the relevant PDE
  2685                              <1> 	; 20/07/2015
  2686                              <1> 	; 18/04/2015
  2687                              <1> 	; 12/04/2015
  2688                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2689                              <1> 	;
  2690                              <1> 	; INPUT ->
  2691                              <1> 	;	EBX = virtual (linear) address
  2692                              <1> 	;	EAX = page directory (physical) address
  2693                              <1> 	; OUTPUT ->
  2694                              <1> 	;	EDX = Page directory entry address
  2695                              <1> 	;	EAX = Page directory entry value
  2696                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2697                              <1> 	; Modified Registers -> EDX, EAX
  2698                              <1> 	;
  2699 00002ED4 89DA                <1> 	mov	edx, ebx
  2700 00002ED6 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2701 00002ED9 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2702 00002EDC 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2703 00002EDE 8B02                <1> 	mov	eax, [edx]
  2704 00002EE0 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2705 00002EE2 751F                <1> 	jnz	short gpte_retn
  2706 00002EE4 F9                  <1> 	stc
  2707                              <1> gpde_retn:	
  2708 00002EE5 C3                  <1> 	retn
  2709                              <1> 
  2710                              <1> get_pte:
  2711                              <1> 		; Get present value of the relevant PTE
  2712                              <1> 	; 29/07/2015
  2713                              <1> 	; 20/07/2015
  2714                              <1> 	; 18/04/2015
  2715                              <1> 	; 12/04/2015
  2716                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2717                              <1> 	;
  2718                              <1> 	; INPUT ->
  2719                              <1> 	;	EBX = virtual (linear) address
  2720                              <1> 	;	EAX = page directory (physical) address
  2721                              <1> 	; OUTPUT ->
  2722                              <1> 	;	EDX = Page table entry address (if CF=0)
  2723                              <1> 	;	      Page directory entry address (if CF=1)
  2724                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2725                              <1> 	;	EAX = Page table entry value (page address)
  2726                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2727                              <1> 	; Modified Registers -> EAX, EDX
  2728                              <1> 	;
  2729 00002EE6 E8E9FFFFFF          <1> 	call 	get_pde
  2730 00002EEB 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2731                              <1> 	;jnc	short gpte_1
  2732                              <1> 	;retn
  2733                              <1> ;gpte_1:
  2734 00002EED 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2735 00002EF1 89DA                <1> 	mov	edx, ebx
  2736 00002EF3 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2737 00002EF6 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2738                              <1> 			 ; clear higher 10 bits (PD bits)
  2739 00002EFC C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2740 00002EFF 01C2                <1> 	add	edx, eax
  2741 00002F01 8B02                <1> 	mov	eax, [edx]
  2742                              <1> gpte_retn:
  2743 00002F03 C3                  <1> 	retn
  2744                              <1> 
  2745                              <1> deallocate_page_dir:
  2746                              <1> 	; 15/09/2015
  2747                              <1> 	; 05/08/2015
  2748                              <1> 	; 30/04/2015
  2749                              <1> 	; 28/04/2015
  2750                              <1> 	; 17/10/2014
  2751                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2752                              <1> 	;
  2753                              <1> 	; INPUT ->
  2754                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2755                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2756                              <1> 	; OUTPUT ->
  2757                              <1> 	;	All of page tables in the page directory
  2758                              <1> 	;	and page dir's itself will be deallocated
  2759                              <1> 	;	except 'read only' duplicated pages (will be converted
  2760                              <1> 	;	to writable pages).
  2761                              <1> 	;
  2762                              <1> 	; Modified Registers -> EAX
  2763                              <1> 	;
  2764                              <1> 	;
  2765 00002F04 56                  <1> 	push	esi
  2766 00002F05 51                  <1> 	push	ecx
  2767 00002F06 50                  <1> 	push	eax
  2768 00002F07 89C6                <1> 	mov	esi, eax 
  2769 00002F09 31C9                <1> 	xor	ecx, ecx
  2770                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2771                              <1> 	; it must not be deallocated
  2772 00002F0B 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2773                              <1> dapd_0:
  2774 00002F0D AD                  <1> 	lodsd
  2775 00002F0E A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2776 00002F10 7409                <1> 	jz	short dapd_1	
  2777 00002F12 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2778 00002F16 E812000000          <1> 	call	deallocate_page_table			
  2779                              <1> dapd_1:
  2780 00002F1B 41                  <1> 	inc	ecx ; page directory entry index
  2781 00002F1C 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2782 00002F22 72E9                <1> 	jb	short dapd_0
  2783                              <1> dapd_2:
  2784 00002F24 58                  <1> 	pop	eax
  2785 00002F25 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2786 00002F2A 59                  <1> 	pop	ecx
  2787 00002F2B 5E                  <1> 	pop	esi
  2788 00002F2C C3                  <1> 	retn
  2789                              <1> 
  2790                              <1> deallocate_page_table:
  2791                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2792                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2793                              <1> 	; 19/09/2015
  2794                              <1> 	; 15/09/2015
  2795                              <1> 	; 05/08/2015
  2796                              <1> 	; 30/04/2015
  2797                              <1> 	; 28/04/2015
  2798                              <1> 	; 24/10/2014
  2799                              <1> 	; 23/10/2014
  2800                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2801                              <1> 	;
  2802                              <1> 	; INPUT ->
  2803                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2804                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2805                              <1> 	;	(ECX = page directory entry index)
  2806                              <1> 	; OUTPUT ->
  2807                              <1> 	;	All of pages in the page table and page table's itself
  2808                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2809                              <1> 	;	(will be converted to writable pages).
  2810                              <1> 	;
  2811                              <1> 	; Modified Registers -> EAX
  2812                              <1> 	;
  2813 00002F2D 56                  <1> 	push	esi
  2814 00002F2E 57                  <1> 	push	edi
  2815 00002F2F 52                  <1> 	push	edx
  2816 00002F30 50                  <1> 	push	eax ; *
  2817 00002F31 89C6                <1> 	mov	esi, eax 
  2818 00002F33 31FF                <1> 	xor	edi, edi ; 0
  2819                              <1> dapt_0:
  2820 00002F35 AD                  <1> 	lodsd
  2821 00002F36 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2822 00002F38 7455                <1> 	jz	short dapt_1
  2823                              <1> 	;
  2824 00002F3A A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2825                              <1> 				  ; (must be 1)
  2826 00002F3C 753F                <1> 	jnz	short dapt_3
  2827                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2828 00002F3E 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2829                              <1> 				   ; as child's page ?
  2830 00002F42 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2831                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2832                              <1> 	; ECX = page directory entry index (0-1023)
  2833 00002F44 53                  <1> 	push	ebx
  2834 00002F45 51                  <1> 	push	ecx
  2835 00002F46 66C1E102            <1> 	shl	cx, 2 ; *4 
  2836 00002F4A 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2837 00002F4C 8B0B                <1> 	mov	ecx, [ebx]
  2838 00002F4E F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2839 00002F51 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2840 00002F53 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2841                              <1> 	; EDI = page table entry index (0-1023)
  2842 00002F58 89FA                <1> 	mov	edx, edi 
  2843 00002F5A 66C1E202            <1> 	shl	dx, 2 ; *4 
  2844 00002F5E 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2845 00002F60 8B1A                <1> 	mov	ebx, [edx]
  2846 00002F62 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2847 00002F65 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2848 00002F67 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2849 00002F6B 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2850 00002F70 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2851 00002F72 7507                <1> 	jne	short dapt_2	; not same page
  2852                              <1> 				; deallocate the child's page
  2853 00002F74 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2854 00002F77 59                  <1> 	pop	ecx
  2855 00002F78 5B                  <1> 	pop	ebx
  2856 00002F79 EB0D                <1> 	jmp	short dapt_4
  2857                              <1> 
  2858                              <1> ; 24/12/2021
  2859                              <1> ; ('dapt_1' is disabled)
  2860                              <1> ;
  2861                              <1> ;dapt_1:
  2862                              <1> ;	or	eax, eax	; swapped page ?
  2863                              <1> ;	jz	short dapt_5	; no
  2864                              <1> ;				; yes
  2865                              <1> ;	shr	eax, 1
  2866                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2867                              <1> ;				  ; on the swap disk (or in file)
  2868                              <1> ;	jmp	short dapt_5
  2869                              <1> dapt_2:
  2870 00002F7B 59                  <1> 	pop	ecx
  2871 00002F7C 5B                  <1> 	pop	ebx
  2872                              <1> dapt_3:	
  2873                              <1> 	; 12/07/2016
  2874 00002F7D 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2875 00002F81 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2876                              <1> 	;
  2877                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2878 00002F83 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2879                              <1> dapt_4:
  2880 00002F88 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2881                              <1> dapt_1:	; 24/12/2021
  2882                              <1> dapt_5:
  2883 00002F8F 47                  <1> 	inc	edi ; page table entry index
  2884 00002F90 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2885 00002F96 729D                <1> 	jb	short dapt_0
  2886                              <1> 	;
  2887 00002F98 58                  <1> 	pop	eax ; *
  2888 00002F99 5A                  <1> 	pop	edx
  2889 00002F9A 5F                  <1> 	pop	edi	
  2890 00002F9B 5E                  <1> 	pop	esi
  2891                              <1> 	;
  2892                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2893                              <1> 	;retn
  2894                              <1> 
  2895                              <1> deallocate_page:
  2896                              <1> 	; 15/09/2015
  2897                              <1> 	; 28/04/2015
  2898                              <1> 	; 10/03/2015
  2899                              <1> 	; 17/10/2014
  2900                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2901                              <1> 	;
  2902                              <1> 	; INPUT -> 
  2903                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2904                              <1> 	; OUTPUT ->
  2905                              <1> 	;	[free_pages] is increased
  2906                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2907                              <1> 	;	CF = 1 if the page is already deallocated
  2908                              <1> 	; 	       (or not allocated) before.  
  2909                              <1> 	;
  2910                              <1> 	; Modified Registers -> EAX
  2911                              <1> 	;
  2912 00002F9C 53                  <1> 	push	ebx
  2913 00002F9D 52                  <1> 	push	edx
  2914                              <1> 	;
  2915 00002F9E C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2916                              <1> 				     ; 12 bits right
  2917                              <1> 				     ; to get page number
  2918 00002FA1 89C2                <1> 	mov	edx, eax
  2919                              <1> 	; 15/09/2015
  2920 00002FA3 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2921                              <1> 				     ; (1 allocation bit = 1 page)
  2922                              <1> 				     ; (1 allocation bytes = 8 pages)
  2923 00002FA6 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2924                              <1> 				     ; (to get 32 bit position)			
  2925                              <1> 	;
  2926 00002FA9 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2927 00002FAE 01D3                <1> 	add	ebx, edx
  2928 00002FB0 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2929                              <1> 				     ; (allocation bit position)	 
  2930 00002FB3 3B15[F46A0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2931                              <1> 				     ; than the address in 'next_page' ?
  2932                              <1> 				     ; (next/first free page value)		
  2933 00002FB9 7306                <1> 	jnb	short dap_1	     ; no	
  2934 00002FBB 8915[F46A0000]      <1> 	mov	[next_page], edx     ; yes
  2935                              <1> dap_1:
  2936 00002FC1 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2937                              <1> 				     ; set relevant bit to 1.
  2938                              <1> 				     ; set CF to the previous bit value	
  2939                              <1> 	;cmc			     ; complement carry flag	
  2940                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2941                              <1> 				     ; if the page is already deallocated
  2942                              <1> 				     ; before.	
  2943 00002FC4 FF05[F06A0000]      <1>         inc     dword [free_pages]
  2944                              <1> dap_2:
  2945 00002FCA 5A                  <1> 	pop	edx
  2946 00002FCB 5B                  <1> 	pop	ebx
  2947 00002FCC C3                  <1> 	retn
  2948                              <1> 
  2949                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2950                              <1> ;;                                                              ;;
  2951                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2952                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2953                              <1> ;;                                                              ;;
  2954                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2955                              <1> 
  2956                              <1> ;;$Revision: 5057 $
  2957                              <1> 
  2958                              <1> 
  2959                              <1> ;;align 4
  2960                              <1> ;;proc alloc_page
  2961                              <1> 
  2962                              <1> ;;        pushfd
  2963                              <1> ;;        cli
  2964                              <1> ;;        push    ebx
  2965                              <1> ;;;//-
  2966                              <1> ;;        cmp     [pg_data.pages_free], 1
  2967                              <1> ;;        jle     .out_of_memory
  2968                              <1> ;;;//-
  2969                              <1> ;;
  2970                              <1> ;;        mov     ebx, [page_start]
  2971                              <1> ;;        mov     ecx, [page_end]
  2972                              <1> ;;.l1:
  2973                              <1> ;;        bsf     eax, [ebx];
  2974                              <1> ;;        jnz     .found
  2975                              <1> ;;        add     ebx, 4
  2976                              <1> ;;        cmp     ebx, ecx
  2977                              <1> ;;        jb      .l1
  2978                              <1> ;;        pop     ebx
  2979                              <1> ;;        popfd
  2980                              <1> ;;        xor     eax, eax
  2981                              <1> ;;        ret
  2982                              <1> ;;.found:
  2983                              <1> ;;;//-
  2984                              <1> ;;        dec     [pg_data.pages_free]
  2985                              <1> ;;        jz      .out_of_memory
  2986                              <1> ;;;//-
  2987                              <1> ;;        btr     [ebx], eax
  2988                              <1> ;;        mov     [page_start], ebx
  2989                              <1> ;;        sub     ebx, sys_pgmap
  2990                              <1> ;;        lea     eax, [eax+ebx*8]
  2991                              <1> ;;        shl     eax, 12
  2992                              <1> ;;;//-       dec [pg_data.pages_free]
  2993                              <1> ;;        pop     ebx
  2994                              <1> ;;        popfd
  2995                              <1> ;;        ret
  2996                              <1> ;;;//-
  2997                              <1> ;;.out_of_memory:
  2998                              <1> ;;        mov     [pg_data.pages_free], 1
  2999                              <1> ;;        xor     eax, eax
  3000                              <1> ;;        pop     ebx
  3001                              <1> ;;        popfd
  3002                              <1> ;;        ret
  3003                              <1> ;;;//-
  3004                              <1> ;;endp
  3005                              <1> 
  3006                              <1> duplicate_page_dir:
  3007                              <1> 	; 21/09/2015
  3008                              <1> 	; 31/08/2015
  3009                              <1> 	; 20/07/2015
  3010                              <1> 	; 28/04/2015
  3011                              <1> 	; 27/04/2015
  3012                              <1> 	; 18/04/2015
  3013                              <1> 	; 12/04/2015
  3014                              <1> 	; 18/10/2014
  3015                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3016                              <1> 	;
  3017                              <1> 	; INPUT -> 
  3018                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3019                              <1> 	;		    page directory.
  3020                              <1> 	; OUTPUT ->
  3021                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3022                              <1> 	;	       page directory.
  3023                              <1> 	;	(New page directory with new page table entries.)
  3024                              <1> 	;	(New page tables with read only copies of the parent's
  3025                              <1> 	;	pages.)
  3026                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3027                              <1> 	;
  3028                              <1> 	; Modified Registers -> none (except EAX)
  3029                              <1> 	;
  3030 00002FCD E802FEFFFF          <1> 	call	allocate_page
  3031 00002FD2 723E                <1> 	jc	short dpd_err
  3032                              <1> 	;
  3033 00002FD4 55                  <1> 	push	ebp ; 20/07/2015
  3034 00002FD5 56                  <1> 	push	esi
  3035 00002FD6 57                  <1> 	push	edi
  3036 00002FD7 53                  <1> 	push	ebx
  3037 00002FD8 51                  <1> 	push	ecx
  3038 00002FD9 8B35[FF6E0000]      <1> 	mov	esi, [u.pgdir]
  3039 00002FDF 89C7                <1> 	mov	edi, eax
  3040 00002FE1 50                  <1> 	push	eax ; save child's page directory address
  3041                              <1> 	; 31/08/2015
  3042                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3043                              <1> 	; (use same system space for all user page tables) 
  3044 00002FE2 A5                  <1> 	movsd
  3045 00002FE3 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3046 00002FE8 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3047                              <1> dpd_0:	
  3048 00002FED AD                  <1> 	lodsd
  3049                              <1> 	;or	eax, eax
  3050                              <1>         ;jnz     short dpd_1
  3051 00002FEE A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3052 00002FF0 7508                <1> 	jnz	short dpd_1
  3053                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3054 00002FF2 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3055 00002FF8 EB0F                <1> 	jmp	short dpd_2
  3056                              <1> dpd_1:	
  3057 00002FFA 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3058 00002FFE 89C3                <1> 	mov	ebx, eax
  3059                              <1> 	; EBX = Parent's page table address
  3060 00003000 E81F000000          <1> 	call	duplicate_page_table
  3061 00003005 720C                <1> 	jc	short dpd_p_err
  3062                              <1> 	; EAX = Child's page table address
  3063 00003007 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3064                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3065                              <1> 			 ; (present, writable, user)
  3066                              <1> dpd_2:
  3067 00003009 AB                  <1> 	stosd
  3068 0000300A E2E1                <1> 	loop	dpd_0
  3069                              <1> 	;
  3070 0000300C 58                  <1> 	pop	eax  ; restore child's page directory address
  3071                              <1> dpd_3:
  3072 0000300D 59                  <1> 	pop	ecx
  3073 0000300E 5B                  <1> 	pop	ebx
  3074 0000300F 5F                  <1> 	pop	edi
  3075 00003010 5E                  <1> 	pop	esi
  3076 00003011 5D                  <1> 	pop	ebp ; 20/07/2015
  3077                              <1> dpd_err:
  3078 00003012 C3                  <1> 	retn
  3079                              <1> dpd_p_err:
  3080                              <1> 	; release the allocated pages missing (recover free space)
  3081 00003013 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3082 00003014 8B1D[FF6E0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3083 0000301A E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3084 0000301F 29C0                <1> 	sub	eax, eax ; 0
  3085 00003021 F9                  <1> 	stc
  3086 00003022 EBE9                <1> 	jmp	short dpd_3	
  3087                              <1> 
  3088                              <1> duplicate_page_table:
  3089                              <1> 	; 31/12/2021
  3090                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3091                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3092                              <1> 	; 21/09/2015
  3093                              <1> 	; 20/07/2015
  3094                              <1> 	; 05/05/2015
  3095                              <1> 	; 28/04/2015
  3096                              <1> 	; 27/04/2015
  3097                              <1> 	; 18/04/2015
  3098                              <1> 	; 18/10/2014
  3099                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3100                              <1> 	;
  3101                              <1> 	; INPUT -> 
  3102                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3103                              <1> 	;       20/02/2017		 
  3104                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3105                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3106                              <1> 	; OUTPUT ->
  3107                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3108                              <1> 	;	      (with 'read only' attribute of page table entries)
  3109                              <1> 	;	20/02/2017
  3110                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3111                              <1> 	;	
  3112                              <1> 	;	CF = 1 -> error 
  3113                              <1> 	;
  3114                              <1> 	; Modified Registers -> EBP (except EAX)
  3115                              <1> 	;
  3116 00003024 E8ABFDFFFF          <1> 	call	allocate_page
  3117 00003029 725B                <1> 	jc	short dpt_err
  3118                              <1> 	;
  3119 0000302B 50                  <1> 	push	eax ; *
  3120 0000302C 56                  <1> 	push	esi
  3121 0000302D 57                  <1> 	push	edi
  3122 0000302E 52                  <1> 	push	edx
  3123 0000302F 51                  <1> 	push	ecx
  3124                              <1> 	;
  3125 00003030 89DE                <1> 	mov	esi, ebx
  3126 00003032 89C7                <1> 	mov	edi, eax
  3127 00003034 89C2                <1> 	mov	edx, eax
  3128 00003036 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3129                              <1> dpt_0:
  3130 0000303C AD                  <1> 	lodsd
  3131 0000303D 21C0                <1> 	and	eax, eax
  3132 0000303F 7435                <1> 	jz	short dpt_3
  3133 00003041 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3134                              <1> 	; 24/12/2021
  3135 00003043 7503                <1> 	jnz	short dpt_1
  3136                              <1> 	;jz	short dpt_p_err
  3137                              <1> 	; 31/12/2021
  3138 00003045 F9                  <1> 	stc
  3139 00003046 EB39                <1> 	jmp	short dpt_p_err
  3140                              <1> 
  3141                              <1> ; 24/12/2021
  3142                              <1> ; ('reload_page' procedure call is disabled)
  3143                              <1> ;
  3144                              <1> ;	; 20/07/2015
  3145                              <1> ;	; ebp = virtual (linear) address of the memory page
  3146                              <1> ;	call	reload_page ; 28/04/2015
  3147                              <1> ;	jc	short dpt_p_err
  3148                              <1> dpt_1:
  3149                              <1> 	; 21/09/2015
  3150 00003048 89C1                <1> 	mov	ecx, eax
  3151 0000304A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3152 0000304E F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3153 00003051 751A                <1> 	jnz	short dpt_2
  3154                              <1> 	; Read only (parent) page
  3155                              <1> 	; 	- there is a third process which uses this page -
  3156                              <1> 	; Allocate a new page for the child process
  3157 00003053 E87CFDFFFF          <1> 	call	allocate_page
  3158 00003058 7227                <1> 	jc	short dpt_p_err
  3159 0000305A 57                  <1> 	push	edi
  3160 0000305B 56                  <1> 	push	esi
  3161 0000305C 89CE                <1> 	mov	esi, ecx
  3162 0000305E 89C7                <1> 	mov	edi, eax
  3163 00003060 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3164 00003065 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3165 00003067 5E                  <1> 	pop	esi
  3166 00003068 5F                  <1> 	pop	edi
  3167                              <1> 	;
  3168                              <1> 
  3169                              <1> ; 24/12/2021
  3170                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3171                              <1> ; 
  3172                              <1> ;	push	ebx
  3173                              <1> ;	push	eax
  3174                              <1> ;	; 20/07/2015
  3175                              <1> ;	mov	ebx, ebp
  3176                              <1> ;	; ebx = virtual (linear) address of the memory page
  3177                              <1> ;	call	add_to_swap_queue
  3178                              <1> ;	pop	eax
  3179                              <1> ;	pop	ebx
  3180                              <1> 
  3181                              <1> 	; 21/09/2015
  3182 00003069 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3183                              <1> 		; user + writable + present page
  3184 0000306B EB09                <1> 	jmp	short dpt_3
  3185                              <1> dpt_2:
  3186                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3187 0000306D 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3188                              <1> 		    ; (read only page!)
  3189 0000306F 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3190 00003072 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3191                              <1> dpt_3:
  3192 00003076 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3193                              <1> 	;
  3194 00003077 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3195                              <1> 	;
  3196 0000307D 39D7                <1> 	cmp	edi, edx
  3197 0000307F 72BB                <1> 	jb	short dpt_0
  3198                              <1> dpt_p_err:
  3199 00003081 59                  <1> 	pop	ecx
  3200 00003082 5A                  <1> 	pop	edx
  3201 00003083 5F                  <1> 	pop	edi
  3202 00003084 5E                  <1> 	pop	esi
  3203 00003085 58                  <1> 	pop	eax ; *
  3204                              <1> dpt_err:
  3205 00003086 C3                  <1> 	retn
  3206                              <1> 
  3207                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3208                              <1> 	; 31/12/2021
  3209                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3210                              <1> 	; 21/09/2015
  3211                              <1> 	; 19/09/2015
  3212                              <1> 	; 17/09/2015
  3213                              <1> 	; 28/08/2015
  3214                              <1> 	; 20/07/2015
  3215                              <1> 	; 28/06/2015
  3216                              <1> 	; 03/05/2015
  3217                              <1> 	; 30/04/2015
  3218                              <1> 	; 18/04/2015
  3219                              <1> 	; 12/04/2015
  3220                              <1> 	; 30/10/2014
  3221                              <1> 	; 11/09/2014
  3222                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3223                              <1> 	;
  3224                              <1> 	; Note: This is not an interrupt/exception handler.
  3225                              <1> 	;	This is a 'page fault remedy' subroutine 
  3226                              <1> 	;	which will be called by standard/uniform
  3227                              <1> 	;	exception handler.
  3228                              <1> 	;
  3229                              <1> 	; INPUT -> 
  3230                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3231                              <1> 	;
  3232                              <1> 	;	cr2 = the virtual (linear) address 
  3233                              <1> 	;	      which has caused to page fault (19/09/2015)
  3234                              <1> 	;
  3235                              <1> 	; OUTPUT ->
  3236                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3237                              <1> 	;	EAX = 0 -> no error
  3238                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3239                              <1> 	;
  3240                              <1> 	; Modified Registers -> none (except EAX)
  3241                              <1> 	;	
  3242                              <1>         ;
  3243                              <1>         ; ERROR CODE:
  3244                              <1> 	;	 31  .....	4   3	2   1	0
  3245                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3246                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3247                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3248                              <1> 	;
  3249                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3250                              <1>     	;		a page-protection violation. When not set,
  3251                              <1> 	;		it was caused by a non-present page.
  3252                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3253                              <1> 	;		a page write. When not set, it was caused
  3254                              <1> 	;		by a page read.
  3255                              <1> 	; U : USER    -	When set, the page fault was caused 
  3256                              <1> 	;		while CPL = 3. 
  3257                              <1> 	;		This does not necessarily mean that
  3258                              <1> 	;		the page fault was a privilege violation.
  3259                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3260                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3261                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3262                              <1> 	;     FETCH	an instruction fetch
  3263                              <1> 	;
  3264                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3265                              <1> 	;  31               22                  12 11                    0
  3266                              <1> 	; +-------------------+-------------------+-----------------------+
  3267                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3268                              <1>        	; +-------------------+-------------------+-----------------------+
  3269                              <1> 	;
  3270                              <1> 
  3271                              <1> 	;; CR3 REGISTER (Control Register 3)
  3272                              <1> 	;  31                                   12             5 4 3 2   0
  3273                              <1> 	; +---------------------------------------+-------------+---+-----+
  3274                              <1>       	; |                                       |  		|P|P|     |
  3275                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3276                              <1>       	; |                                       | 		|D|T|     |
  3277                              <1>    	; +---------------------------------------+-------------+---+-----+
  3278                              <1> 	;
  3279                              <1> 	;	PWT    - WRITE THROUGH
  3280                              <1> 	;	PCD    - CACHE DISABLE		
  3281                              <1> 	;
  3282                              <1> 	;
  3283                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3284                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3285                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3286                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3287                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3288                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3289                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3290                              <1> 	;
  3291                              <1>         ;       P      - PRESENT
  3292                              <1>         ;       R/W    - READ/WRITE
  3293                              <1>         ;       U/S    - USER/SUPERVISOR
  3294                              <1> 	;	PWT    - WRITE THROUGH
  3295                              <1> 	;	PCD    - CACHE DISABLE	
  3296                              <1> 	;	A      - ACCESSED	
  3297                              <1>         ;       D      - DIRTY (IGNORED)
  3298                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3299                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3300                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3301                              <1> 	;
  3302                              <1> 	;
  3303                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3304                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3305                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3306                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3307                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3308                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3309                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3310                              <1> 	;
  3311                              <1>         ;       P      - PRESENT
  3312                              <1>         ;       R/W    - READ/WRITE
  3313                              <1>         ;       U/S    - USER/SUPERVISOR
  3314                              <1> 	;	PWT    - WRITE THROUGH
  3315                              <1> 	;	PCD    - CACHE DISABLE	
  3316                              <1> 	;	A      - ACCESSED	
  3317                              <1>         ;       D      - DIRTY
  3318                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3319                              <1> 	;	G      - GLOBAL	 
  3320                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3321                              <1> 	;
  3322                              <1> 	;
  3323                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3324                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3325                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3326                              <1>       	; |                                       |     | | | | | | |U|R| |
  3327                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3328                              <1>       	; |                                       |     | | | | | | |S|W| |
  3329                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3330                              <1> 	;
  3331                              <1>         ;       P      - PRESENT
  3332                              <1>         ;       R/W    - READ/WRITE
  3333                              <1>         ;       U/S    - USER/SUPERVISOR
  3334                              <1>         ;       D      - DIRTY
  3335                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3336                              <1> 	;
  3337                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3338                              <1> 	;
  3339                              <1> 	;
  3340                              <1> 	;; Invalid Page Table Entry
  3341                              <1> 	; 31                                                           1 0
  3342                              <1>       	; +-------------------------------------------------------------+-+
  3343                              <1>       	; |                                                             | |
  3344                              <1>       	; |                          AVAILABLE                          |0|
  3345                              <1>       	; |                                                             | |
  3346                              <1>       	; +-------------------------------------------------------------+-+
  3347                              <1> 	;
  3348                              <1> 
  3349 00003087 53                  <1> 	push	ebx
  3350 00003088 52                  <1> 	push	edx
  3351 00003089 51                  <1> 	push	ecx
  3352                              <1> 	;
  3353                              <1> 	; 21/09/2015 (debugging)
  3354 0000308A FF05[0F6F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3355 00003090 FF05[A06B0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3356                              <1> 	; 28/06/2015
  3357                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3358 00003096 8A15[986B0000]      <1> 	mov	dl, [error_code]
  3359                              <1> 	;
  3360 0000309C F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3361                              <1> 			; sign
  3362 0000309F 7425                <1> 	jz	short pfh_alloc_np
  3363                              <1> 	; 
  3364                              <1> 	; If it is not a 'write on read only page' type page fault
  3365                              <1> 	; major page fault error with minor reason must be returned without 
  3366                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3367                              <1> 	; after return here!
  3368                              <1> 	; Page fault will be remedied, by copying page contents
  3369                              <1> 	; to newly allocated page with write permission;
  3370                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3371                              <1> 	; used for working with minimum possible memory usage. 
  3372                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3373                              <1> 	; process with 'read only' flag. If the child process attempts to
  3374                              <1> 	; write on these read only pages, page fault will be directed here
  3375                              <1> 	; for allocating a new page with same data/content. 
  3376                              <1> 	;
  3377                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3378                              <1> 	; will not force to separate CODE and DATA space 
  3379                              <1> 	; in a process/program... 
  3380                              <1> 	; CODE segment/section may contain DATA!
  3381                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3382                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3383                              <1> 	;	
  3384 000030A1 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3385                              <1> 			; sign
  3386 000030A4 7418                <1>         jz      pfh_p_err
  3387                              <1> 	; 31/08/2015
  3388 000030A6 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3389                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3390 000030A9 7413                <1>         jz	short pfh_pv_err
  3391                              <1> 	;
  3392                              <1> 	; make a new page and copy the parent's page content
  3393                              <1> 	; as the child's new page content
  3394                              <1> 	;
  3395 000030AB 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3396                              <1> 			 ; which has caused to page fault
  3397 000030AE E87C000000          <1> 	call 	copy_page
  3398 000030B3 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3399                              <1> 	;
  3400 000030B5 EB72                <1>         jmp     pfh_cpp_ok
  3401                              <1> 
  3402                              <1> 	; 31/12/2021 (short jump)
  3403                              <1> pfh_im_err:
  3404 000030B7 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3405                              <1> 			; Major (Primary) Error: Page Fault
  3406                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3407 000030BC EB6D                <1> 	jmp	short pfh_err_retn
  3408                              <1> 
  3409                              <1> 	; 31/12/2021
  3410                              <1> pfh_p_err: ; 09/03/2015
  3411                              <1> pfh_pv_err:
  3412                              <1> 	; Page fault was caused by a protection-violation
  3413 000030BE B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3414                              <1> 			; Major (Primary) Error: Page Fault
  3415                              <1> 			; Minor (Secondary) Error: Protection violation !
  3416 000030C3 F9                  <1> 	stc
  3417 000030C4 EB65                <1> 	jmp	short pfh_err_retn
  3418                              <1> 	
  3419                              <1> pfh_alloc_np:
  3420 000030C6 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3421 000030CB 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3422                              <1> pfh_chk_cpl:
  3423                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3424                              <1> 		; (Lower 12 bits are ZERO, because 
  3425                              <1> 		;	the address is on a page boundary)
  3426 000030CD 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3427 000030D0 7505                <1> 	jnz	short pfh_um
  3428                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3429 000030D2 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3430                              <1> 			 ; of the current/active page directory
  3431                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3432                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3433 000030D5 EB06                <1> 	jmp	short pfh_get_pde
  3434                              <1> 	;
  3435                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3436 000030D7 8B1D[FF6E0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3437                              <1> 			; Physical address of the USER's page directory
  3438                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3439                              <1> pfh_get_pde:
  3440 000030DD 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3441 000030E0 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3442                              <1> 			 ; which has been caused to page fault
  3443                              <1> 			 ;
  3444 000030E3 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3445 000030E6 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3446                              <1> 	;
  3447 000030E9 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3448 000030EB 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3449 000030ED F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3450 000030F0 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3451                              <1> 			  	  ; set/validate page directory entry
  3452 000030F2 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3453 000030F7 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3454 000030F9 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3455 000030FB EB16                <1> 	jmp	short pfh_get_pte
  3456                              <1> pfh_set_pde:
  3457                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3458                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3459                              <1> 	;
  3460 000030FD 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3461 000030FF 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3462 00003101 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3463 00003103 89C3                <1> 	mov	ebx, eax
  3464 00003105 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3465 0000310A 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3466                              <1> pfh_spde_1:
  3467                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3468 0000310C 89C1                <1> 	mov	ecx, eax
  3469 0000310E E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3470                              <1> pfh_get_pte:
  3471 00003113 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3472                              <1> 			 ; which has been caused to page fault
  3473 00003116 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3474 00003118 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3475                              <1> 			 ; higher 20 bits of the page fault address 
  3476 0000311B 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3477 00003120 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3478 00003123 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3479                              <1> ; 24/12/2021
  3480                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3481                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3482                              <1> ; 24/12/2021
  3483                              <1> ; ('swap_in' procedure call has been disabled)
  3484                              <1> ;
  3485                              <1> ;	and	eax, eax
  3486                              <1> ;	jz	short pfh_gpte_1
  3487                              <1> ;	; 20/07/2015
  3488                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3489                              <1> ;	push	ebp ; 20/07/2015
  3490                              <1> ;	mov	ebp, cr2
  3491                              <1> ;		; ECX = physical address of the page table entry
  3492                              <1> ;		; EBX = Memory page address (physical!)
  3493                              <1> ;		; EAX = Swap disk (offset) address
  3494                              <1> ;		; EBP = virtual address (page fault address)
  3495                              <1> ;	call	swap_in
  3496                              <1> ;	pop	ebp
  3497                              <1> ;	jc      short pfh_err_retn
  3498                              <1> ;	xchg	ecx, ebx
  3499                              <1> ;		; EBX = physical address of the page table entry
  3500                              <1> ;		; ECX = new page
  3501                              <1> pfh_gpte_1:
  3502 00003125 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3503 00003127 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3504                              <1> pfh_cpp_ok:
  3505                              <1> ; 24/12/2021
  3506                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3507                              <1> ;
  3508                              <1> ;	; 20/07/2015
  3509                              <1> ;	mov	ebx, cr2
  3510                              <1> ;	call 	add_to_swap_queue
  3511                              <1> 	;
  3512                              <1> 	; The new PTE (which contains the new page) will be added to 
  3513                              <1> 	; the swap queue, here. 
  3514                              <1> 	; (Later, if memory will become insufficient, 
  3515                              <1> 	; one page will be swapped out which is at the head of 
  3516                              <1> 	; the swap queue by using FIFO and access check methods.)
  3517                              <1> 	;
  3518 00003129 31C0                <1> 	xor	eax, eax  ; 0
  3519                              <1> 	;
  3520                              <1> pfh_err_retn:
  3521 0000312B 59                  <1> 	pop	ecx
  3522 0000312C 5A                  <1> 	pop	edx
  3523 0000312D 5B                  <1> 	pop	ebx
  3524 0000312E C3                  <1> 	retn 
  3525                              <1> 	
  3526                              <1> copy_page:
  3527                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3528                              <1> 	; 16/04/2021
  3529                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3530                              <1> 	; 22/09/2015
  3531                              <1> 	; 21/09/2015
  3532                              <1> 	; 19/09/2015
  3533                              <1> 	; 07/09/2015
  3534                              <1> 	; 31/08/2015
  3535                              <1> 	; 20/07/2015
  3536                              <1> 	; 05/05/2015
  3537                              <1> 	; 03/05/2015
  3538                              <1> 	; 18/04/2015
  3539                              <1> 	; 12/04/2015
  3540                              <1> 	; 30/10/2014
  3541                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3542                              <1> 	;
  3543                              <1> 	; INPUT -> 
  3544                              <1> 	;	EBX = Virtual (linear) address of source page
  3545                              <1> 	;	     (Page fault address)
  3546                              <1> 	; OUTPUT ->
  3547                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3548                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3549                              <1> 	;	EAX = 0 (CF = 1) 
  3550                              <1> 	;		if there is not a free page to be allocated
  3551                              <1> 	;	(page content of the source page will be copied
  3552                              <1> 	;	onto the target/new page) 	
  3553                              <1> 	;
  3554                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3555                              <1> 	;
  3556                              <1> 
  3557                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3558                              <1> 	; INPUT: 
  3559                              <1> 	;	EBX = Virtual (linear) address of source page
  3560                              <1> 	;	     (Page fault address)
  3561                              <1> 	; OUTPUT:
  3562                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3563                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3564                              <1> 	;	EAX = 0 (CF = 1) 
  3565                              <1> 	;		if there is not a free page to be allocated
  3566                              <1> 	;	(page content of the source page will be copied
  3567                              <1> 	;	onto the target/new page) 	
  3568                              <1> 	;
  3569                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3570                              <1> 	
  3571 0000312F 56                  <1> 	push	esi ; *
  3572 00003130 57                  <1> 	push	edi ; **
  3573                              <1> 	; 16/04/2021
  3574                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3575                              <1> 	;push	ebx ; ***
  3576                              <1> 	;push	ecx ; ****
  3577 00003131 31F6                <1> 	xor 	esi, esi
  3578 00003133 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3579 00003136 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3580 00003138 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3581 0000313B 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3582 0000313E 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3583 00003140 031D[FF6E0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3584 00003146 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3585 00003148 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3586 0000314C 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3587 0000314E 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3588 00003154 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3589 00003158 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3590                              <1> 	; 07/09/2015
  3591 0000315A 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3592                              <1> 				     ; read only page as a child process?)	
  3593 0000315F 7509                <1> 	jnz	short cpp_0 ; yes
  3594 00003161 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3595 00003163 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3596 00003168 EB32                <1> 	jmp	short cpp_1
  3597                              <1> cpp_0:
  3598 0000316A 89FE                <1> 	mov	esi, edi
  3599 0000316C 0335[036F0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3600 00003172 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3601 00003174 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3602 00003178 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3603 0000317A 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3604 00003180 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3605 00003184 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3606 00003186 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3607                              <1> 	; 21/09/2015
  3608 00003188 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3609 0000318A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3610                              <1> 	;
  3611 0000318E F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3612 00003191 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3613                              <1> 	;
  3614 00003193 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3615 00003198 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3616 0000319A 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3617                              <1> 			    ; Convert child's page to writable page
  3618                              <1> cpp_1:
  3619 0000319C E833FCFFFF          <1> 	call	allocate_page
  3620 000031A1 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3621 000031A3 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3622 000031A5 7405                <1> 	jz	short cpp_2
  3623                              <1> 		; Convert read only page to writable page 
  3624                              <1> 		;(for the parent of the current process)
  3625                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3626                              <1> 	; 22/09/2015
  3627 000031A7 890E                <1> 	mov	[esi], ecx
  3628 000031A9 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3629                              <1> 				 ; 1+2+4 = 7
  3630                              <1> cpp_2:
  3631 000031AC 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3632                              <1> 	; 07/09/2015
  3633 000031AE 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3634 000031B0 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3635 000031B5 F3A5                <1> 	rep	movsd ; 31/08/2015
  3636                              <1> cpp_3:		
  3637 000031B7 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3638 000031B9 8903                <1> 	mov	[ebx], eax ; Update PTE
  3639 000031BB 28C0                <1> 	sub	al, al ; clear attributes
  3640                              <1> cpp_4:
  3641                              <1> 	; 16/04/2021
  3642                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3643                              <1> 	;pop	ecx ; ****
  3644                              <1> 	;pop	ebx ; ***
  3645 000031BD 5F                  <1> 	pop	edi ; **
  3646 000031BE 5E                  <1> 	pop	esi ; *
  3647 000031BF C3                  <1> 	retn
  3648                              <1> 
  3649                              <1> ;; 28/04/2015
  3650                              <1> ;; 24/10/2014
  3651                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3652                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3653                              <1> ;;
  3654                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3655                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3656                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3657                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3658                              <1> ;;
  3659                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3660                              <1> ;;
  3661                              <1> ;; Method:
  3662                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3663                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3664                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3665                              <1> ;;	When a new page is being allocated, swap queue is updated
  3666                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3667                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3668                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3669                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3670                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3671                              <1> ;;	offset value becomes it's previous offset value - 4.
  3672                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3673                              <1> ;;	the queue/list is not shifted.
  3674                              <1> ;;	After the queue/list shift, newly allocated page is added
  3675                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3676                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3677                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3678                              <1> ;;	
  3679                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3680                              <1> ;;	the first non-accessed, writable page in the list, 
  3681                              <1> ;;	from the head to the tail. The list is shifted to left 
  3682                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3683                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3684                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3685                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3686                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3687                              <1> ;;	procedure will be failed)...
  3688                              <1> ;;
  3689                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3690                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3691                              <1> ;;	(PTE) will be added to the tail of the queue after
  3692                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3693                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3694                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3695                              <1> ;;
  3696                              <1> ;;
  3697                              <1> ;;	
  3698                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3699                              <1> ;;
  3700                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3701                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3702                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3703                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3704                              <1> ;;
  3705                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3706                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3707                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3708                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3709                              <1> ;; 		 (entire swap space must be accessed by using
  3710                              <1> ;;		 31 bit offset address) 
  3711                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3712                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3713                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3714                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3715                              <1> ;;
  3716                              <1> ;; 					
  3717                              <1> ;; Method:
  3718                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3719                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3720                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3721                              <1> ;;	Swapping out is performed by using swap page queue.
  3722                              <1> ;;
  3723                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3724                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3725                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3726                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3727                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3728                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3729                              <1> ;;	calculated by adding offset value to the swap partition's 
  3730                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3731                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3732                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3733                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3734                              <1> ;;	is in a partitioned virtual hard disk.) 
  3735                              <1> ;;
  3736                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3737                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3738                              <1> ;;
  3739                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3740                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3741                              <1> ;;
  3742                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3743                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3744                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3745                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3746                              <1> ;;	it means relevant (respective) block is in use, and, 
  3747                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3748                              <1> ;;      swap disk/file block is free.
  3749                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3750                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3751                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3752                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3753                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3754                              <1> ;;	------------------------------------------------------------
  3755                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3756                              <1> ;;	------------------------------------------------------------
  3757                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3758                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3759                              <1> ;;
  3760                              <1> ;;	..............................................................
  3761                              <1> ;;
  3762                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3763                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3764                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3765                              <1> ;;	position with value of 1 on the table is converted to swap
  3766                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3767                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3768                              <1> ;;	number of physical swap disk or virtual swap disk)
  3769                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3770                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3771                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3772                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3773                              <1> ;;	If disk write procedure returns with error or free count of 
  3774                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3775                              <1> ;;	'insufficient memory error' (cf=1). 
  3776                              <1> ;;
  3777                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3778                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3779                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3780                              <1> ;;	free blocks after a disk write error. It will return to 
  3781                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3782                              <1> ;;
  3783                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3784                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3785                              <1> ;;	address (cf=0). 
  3786                              <1> ;;
  3787                              <1> ;;	..............................................................
  3788                              <1> ;;
  3789                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3790                              <1> ;;	file sectors at specified memory page. Then page allocation
  3791                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3792                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3793                              <1> ;;	to do, except to terminate the process which is the owner of
  3794                              <1> ;;	the swapped page.
  3795                              <1> ;;
  3796                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3797                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3798                              <1> ;;	updates [swpd_first] pointer if it is required.
  3799                              <1> ;;
  3800                              <1> ;;	..............................................................	 
  3801                              <1> ;;
  3802                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3803                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3804                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3805                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3806                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3807                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3808                              <1> ;;
  3809                              <1> 
  3810                              <1> ; 24/12/2021
  3811                              <1> ; ('swap_in' procedure call is disabled)
  3812                              <1> 
  3813                              <1> ;swap_in:
  3814                              <1> 	; 31/08/2015
  3815                              <1> 	; 20/07/2015
  3816                              <1> 	; 28/04/2015
  3817                              <1> 	; 18/04/2015
  3818                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3819                              <1> 	;
  3820                              <1> 	; INPUT -> 
  3821                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3822                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3823                              <1> 	;	EAX = Offset Address for the swapped page on the
  3824                              <1> 	;	      swap disk or in the swap file.
  3825                              <1> 	;
  3826                              <1> 	; OUTPUT ->
  3827                              <1> 	;	EAX = 0 if loading at memory has been successful
  3828                              <1> 	;
  3829                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3830                              <1> 	;		  or sector not present or drive not ready
  3831                              <1> 	;	     EAX = Error code
  3832                              <1> 	;	     [u.error] = EAX 
  3833                              <1> 	;		       = The last error code for the process
  3834                              <1> 	;		         (will be reset after returning to user)	  
  3835                              <1> 	;
  3836                              <1> 	; Modified Registers -> EAX
  3837                              <1> 	;
  3838                              <1> 
  3839                              <1> ;       cmp     dword [swp_drv], 0
  3840                              <1> ;	jna	short swpin_dnp_err
  3841                              <1> ;
  3842                              <1> ;	cmp	eax, [swpd_size]
  3843                              <1> ;	jnb	short swpin_snp_err
  3844                              <1> ;
  3845                              <1> ;	push	esi
  3846                              <1> ;	push	ebx
  3847                              <1> ;	push	ecx
  3848                              <1> ;	mov	esi, [swp_drv]	
  3849                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3850                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3851                              <1> ;		; size different than 512 bytes, logical disk sector
  3852                              <1> ;		; size is 512 bytes and disk reading procedure
  3853                              <1> ;		; will be performed for reading 4096 bytes
  3854                              <1> ;		; (2*2048, 8*512). 
  3855                              <1> ;	; ESI = Logical disk description table address
  3856                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3857                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3858                              <1> ;	; ECX = Sector count ; 8 sectors
  3859                              <1> ;	push	eax
  3860                              <1> ;	call	logical_disk_read
  3861                              <1> ;	pop	eax
  3862                              <1> ;	jnc	short swpin_read_ok
  3863                              <1> ;	;
  3864                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3865                              <1> ;	mov	[u.error], eax
  3866                              <1> ;	jmp	short swpin_retn
  3867                              <1> ;	;
  3868                              <1> ;swpin_read_ok:
  3869                              <1> ;	; EAX = Offset address (logical sector number)
  3870                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3871                              <1> ;	;
  3872                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3873                              <1> ;	; 20/07/2015
  3874                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3875                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3876                              <1> ;	mov	bl, [u.uno] ; current process number
  3877                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3878                              <1> ;	call	swap_queue_shift
  3879                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3880                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3881                              <1> ;	; zf = 1
  3882                              <1> ;swpin_retn:
  3883                              <1> ;	pop	ecx
  3884                              <1> ;	pop	ebx
  3885                              <1> ;	pop	esi
  3886                              <1> ;	retn
  3887                              <1> ;
  3888                              <1> ;swpin_dnp_err:
  3889                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3890                              <1> ;swpin_err_retn:
  3891                              <1> ;	mov	[u.error], eax
  3892                              <1> ;	stc
  3893                              <1> ;	retn
  3894                              <1> ;
  3895                              <1> ;swpin_snp_err:
  3896                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3897                              <1> ;	jmp	short swpin_err_retn
  3898                              <1> 
  3899                              <1> ; 24/12/2021
  3900                              <1> ; ('swap_out' procedure call is disabled)
  3901                              <1> 
  3902                              <1> ;swap_out:
  3903                              <1> 	; 10/06/2016
  3904                              <1> 	; 07/06/2016
  3905                              <1>         ; 23/05/2016
  3906                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3907                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3908                              <1> 	;
  3909                              <1> 	; INPUT -> 
  3910                              <1> 	;	none
  3911                              <1> 	;
  3912                              <1> 	; OUTPUT ->
  3913                              <1> 	;	EAX = Physical page address (which is swapped out
  3914                              <1> 	;	      for allocating a new page)
  3915                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3916                              <1> 	;		  or sector not present or drive not ready
  3917                              <1> 	;	     EAX = Error code
  3918                              <1> 	;	     [u.error] = EAX 
  3919                              <1> 	;		       = The last error code for the process
  3920                              <1> 	;		         (will be reset after returning to user)	  
  3921                              <1> 	;
  3922                              <1> 	; Modified Registers -> none (except EAX)
  3923                              <1> 	;
  3924                              <1> 
  3925                              <1> ;	cmp 	word [swpq_count], 1
  3926                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3927                              <1> ;
  3928                              <1> ;       ;cmp    dword [swp_drv], 1
  3929                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3930                              <1> ;
  3931                              <1> ;       cmp     dword [swpd_free], 1
  3932                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3933                              <1> ;
  3934                              <1> ;	push	ebx ; *
  3935                              <1> ;swpout_1:
  3936                              <1> ;	; 10/06/2016
  3937                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3938                              <1> ;	call	swap_queue_shift
  3939                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3940                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3941                              <1> ;				       ; pointer in the swap queue
  3942                              <1> ;	; EAX = PTE value of the page
  3943                              <1> ;	; EBX = PTE address of the page
  3944                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3945                              <1> ;	;
  3946                              <1> ;	; 07/06/2016
  3947                              <1> ;	; 19/05/2016
  3948                              <1> ;	; check this page is in timer events or not
  3949                              <1> ;	
  3950                              <1> ;swpout_timer_page_0:
  3951                              <1> ;	push	edx ; **
  3952                              <1> ;
  3953                              <1> ;	; 07/06/2016
  3954                              <1> ;	cmp	byte [timer_events], 0 
  3955                              <1> ;	jna	short swpout_2
  3956                              <1> ;	;
  3957                              <1> ;	mov	dl, [timer_events]
  3958                              <1> ;
  3959                              <1> ;	push	ecx ; ***
  3960                              <1> ;	push	ebx ; ****
  3961                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3962                              <1> ;			       ; structures 
  3963                              <1> ;swpout_timer_page_1:
  3964                              <1> ;	mov	cl, [ebx]
  3965                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3966                              <1> ;	jz	short swpout_timer_page_3
  3967                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3968                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3969                              <1> ;				; of the response byte address, to
  3970                              <1> ;				; get beginning of the page address)
  3971                              <1> ;	cmp	eax, ecx
  3972                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3973                              <1> ;	
  3974                              <1> ;	; !same page!
  3975                              <1> ;	;
  3976                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3977                              <1> ;	; This page will be used by the kernel to put timer event
  3978                              <1> ;	; response (signal return) byte at the requested address;
  3979                              <1> ;	; in order to prevent a possible wrong write (while
  3980                              <1> ;	; this page is swapped out) on physical memory,
  3981                              <1> ;	; we must protect this page against to be swapped out!
  3982                              <1> ;	;
  3983                              <1> ;	pop	ebx ; ****
  3984                              <1> ;	pop	ecx ; ***
  3985                              <1> ;	pop	edx ; **
  3986                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3987                              <1> ; 
  3988                              <1> ;swpout_timer_page_2:
  3989                              <1> ;	; 07/06/2016
  3990                              <1> ;	dec	dl
  3991                              <1> ;	jz	short swpout_timer_page_4
  3992                              <1> ;swpout_timer_page_3:
  3993                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3994                              <1> ;	;jnb	short swpout_timer_page_4
  3995                              <1> ;	add	ebx, 16
  3996                              <1> ;	jmp	short swpout_timer_page_1	
  3997                              <1> ;
  3998                              <1> ;swpout_timer_page_4:
  3999                              <1> ;	pop	ebx ; ****
  4000                              <1> ;	pop	ecx ; ***
  4001                              <1> ;swpout_2:
  4002                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4003                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4004                              <1> ;	;
  4005                              <1> ;	call	link_swap_block
  4006                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4007                              <1> ;				       ; because [swpd_free] value
  4008                              <1> ;				       ; was checked at the beginging. 	
  4009                              <1> ;	pop	edx ; **
  4010                              <1> ;	pop	ebx ; *
  4011                              <1> ;	jmp	short swpout_nfspc_err 
  4012                              <1> ;swpout_3:
  4013                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4014                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4015                              <1> ;	;	
  4016                              <1> ;	push	esi ; **
  4017                              <1> ;	push	ecx ; ***
  4018                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4019                              <1> ;	mov	esi, [swp_drv]	
  4020                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4021                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4022                              <1> ;		; size different than 512 bytes, logical disk sector
  4023                              <1> ;		; size is 512 bytes and disk writing procedure
  4024                              <1> ;		; will be performed for writing 4096 bytes
  4025                              <1> ;		; (2*2048, 8*512). 
  4026                              <1> ;	; ESI = Logical disk description table address
  4027                              <1> ;	; EBX = Buffer (Page) address
  4028                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4029                              <1> ;	; ECX = Sector count ; 8 sectors
  4030                              <1> ;	; edx = PTE address
  4031                              <1> ;	call	logical_disk_write
  4032                              <1> ;	; edx = PTE address
  4033                              <1> ;	pop	ecx ; sector address	
  4034                              <1> ;	jnc	short swpout_write_ok
  4035                              <1> ;	;
  4036                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4037                              <1> ;swpout_dw_err:
  4038                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4039                              <1> ;	mov	[u.error], eax
  4040                              <1> ;	jmp	short swpout_retn
  4041                              <1> ;	;
  4042                              <1> ;swpout_write_ok:
  4043                              <1> ;	; EBX = Buffer (page) address
  4044                              <1> ;	; EDX = Page Table Entry address
  4045                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4046                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4047                              <1> ;	mov 	[edx], ecx 
  4048                              <1> ;		; bit 0 = 0 (swapped page)
  4049                              <1> ;	mov	eax, ebx
  4050                              <1> ;swpout_retn:
  4051                              <1> ;	pop	ecx ; ***
  4052                              <1> ;	pop	esi ; **
  4053                              <1> ;	pop	ebx ; *
  4054                              <1> ;	retn
  4055                              <1> ;
  4056                              <1> ;;swpout_dnp_err:
  4057                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4058                              <1> ;;	jmp	short swpout_err_retn
  4059                              <1> ;swpout_nfspc_err:
  4060                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4061                              <1> ;swpout_err_retn:
  4062                              <1> ;	mov	[u.error], eax
  4063                              <1> ;	;stc
  4064                              <1> ;	retn
  4065                              <1> ;swpout_npts_err:
  4066                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4067                              <1> ;	pop	ebx
  4068                              <1> ;	jmp	short swpout_err_retn
  4069                              <1> ;swpout_im_err:
  4070                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4071                              <1> ;	jmp	short swpout_err_retn
  4072                              <1> 
  4073                              <1> ; 24/12/2021
  4074                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4075                              <1> 
  4076                              <1> ;swap_queue_shift:
  4077                              <1> 	; 26/03/2017
  4078                              <1> 	; 10/06/2016
  4079                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4080                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4081                              <1> 	;
  4082                              <1> 	; INPUT ->
  4083                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4084                              <1> 	;	      and process number combination (bit 0 to 11)
  4085                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4086                              <1> 	;	
  4087                              <1> 	; OUTPUT ->
  4088                              <1> 	;	If EBX input > 0 
  4089                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4090                              <1> 	; 	   from the tail to the head, up to entry offset
  4091                              <1> 	; 	   which points to EBX input value or nothing
  4092                              <1> 	;	   to do if EBX value is not found on the queue.
  4093                              <1> 	;	   (The entry -with EBX value- will be removed
  4094                              <1> 	;	   from the queue if it is found.)
  4095                              <1> 	;
  4096                              <1> 	;	   EAX = 0		
  4097                              <1> 	;
  4098                              <1> 	;	If EBX input = 0
  4099                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4100                              <1> 	; 	   from the tail to the head, if the PTE address
  4101                              <1> 	;	   which is pointed in head of the queue is marked
  4102                              <1> 	;	   as "accessed" or it is marked as "non present".
  4103                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4104                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4105                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4106                              <1> 	;	   -without dropping pointer of the PTE from 
  4107                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4108                              <1> 	;	   Pointer in the head will be moved into the tail,
  4109                              <1> 	;	   other PTEs will be shifted on head direction.)
  4110                              <1> 	;
  4111                              <1> 	;	   Swap queue will be shifted up to the first
  4112                              <1> 	;	   'present' or 'non accessed' page will be found
  4113                              <1> 	;	   (as pointed) on the queue head (then it will be
  4114                              <1>         ;          removed/dropped from the queue).
  4115                              <1> 	;
  4116                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4117                              <1> 	;		 (it's pointer -virtual address-) dropped
  4118                              <1> 	;		 (removed) from swap queue.
  4119                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4120                              <1> 	;	         which is (it's pointer -virtual address-)
  4121                              <1> 	;		 dropped (removed) from swap queue.
  4122                              <1> 	;
  4123                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4124                              <1> 	;
  4125                              <1> 	; Modified Registers -> EAX, EBX
  4126                              <1> 	;
  4127                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4128                              <1> ;	and	ax, ax
  4129                              <1> ;	jz	short swpqs_retn
  4130                              <1> ;	push	edi
  4131                              <1> ;	push	esi
  4132                              <1> ;	push	ecx
  4133                              <1> ;	mov	esi, swap_queue
  4134                              <1> ;	mov	ecx, eax
  4135                              <1> ;	or	ebx, ebx
  4136                              <1> ;	jz	short swpqs_7
  4137                              <1> ;swpqs_1:
  4138                              <1> ;	lodsd
  4139                              <1> ;	cmp	eax, ebx
  4140                              <1> ;	je	short swpqs_2
  4141                              <1> ;	loop	swpqs_1
  4142                              <1> ;	; 10/06/2016
  4143                              <1> ;	sub	eax, eax 
  4144                              <1> ;	jmp	short swpqs_6
  4145                              <1> ;swpqs_2:
  4146                              <1> ;	mov	edi, esi
  4147                              <1> ;	sub 	edi, 4
  4148                              <1> ;swpqs_3:
  4149                              <1> ;	dec	word [swpq_count]
  4150                              <1> ;	jz	short swpqs_5
  4151                              <1> ;swpqs_4:
  4152                              <1> ;	dec 	ecx
  4153                              <1> ;	rep	movsd	; shift up (to the head)
  4154                              <1> ;swpqs_5:
  4155                              <1> ;	xor	eax, eax
  4156                              <1> ;	mov	[edi], eax
  4157                              <1> ;swpqs_6:
  4158                              <1> ;	pop	ecx
  4159                              <1> ;	pop	esi
  4160                              <1> ;	pop	edi
  4161                              <1> ;swpqs_retn:
  4162                              <1> ;	retn		
  4163                              <1> ;swpqs_7:
  4164                              <1> ;	mov	edi, esi ; head
  4165                              <1> ;	lodsd
  4166                              <1> ;	; 20/07/2015
  4167                              <1> ;	mov	ebx, eax
  4168                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4169                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4170                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4171                              <1> ;		      ; ax = process number (1 to 4095)
  4172                              <1> ;	cmp	al, [u.uno]
  4173                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4174                              <1> ;	jne	short swpqs_8
  4175                              <1> ;	mov	eax, [u.pgdir]
  4176                              <1> ;	jmp	short swpqs_9
  4177                              <1> ;swpqs_8:
  4178                              <1> ;	; 09/06/2016
  4179                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4180                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4181                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4182                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4183                              <1> ;
  4184                              <1> ;	;shl	ax, 2
  4185                              <1> ;	shl	al, 2
  4186                              <1> ;	mov 	eax, [eax+p.upage-4]
  4187                              <1> ;	or	eax, eax
  4188                              <1> ;	jz	short swpqs_3 ; invalid upage
  4189                              <1> ;	add	eax, u.pgdir - user
  4190                              <1> ;			 ; u.pgdir value for the process
  4191                              <1> ;			 ; is in [eax]
  4192                              <1> ;	mov	eax, [eax]
  4193                              <1> ;	and	eax, eax
  4194                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4195                              <1> ;swpqs_9:
  4196                              <1> ;	push	edx
  4197                              <1> ;	; eax = page directory
  4198                              <1> ;	; ebx = virtual address
  4199                              <1> ;	call	get_pte
  4200                              <1> ;	mov	ebx, edx	; PTE address
  4201                              <1> ;	pop	edx
  4202                              <1> ;	; 10/06/2016
  4203                              <1> ;	jc	short swpqs_13 ; empty PDE
  4204                              <1> ;	; EAX = PTE value
  4205                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4206                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4207                              <1> ;			        ; from the queue (head)
  4208                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4209                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4210                              <1> ;			        ; from the queue (head) 	
  4211                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4212                              <1> ;	;jnz	short swpqs_11  ; present
  4213                              <1> ;			        ; accessed page
  4214                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4215                              <1> ;	jc	short swpqs_11  ; accessed page
  4216                              <1> ;
  4217                              <1> ;	dec	ecx
  4218                              <1> ;	mov	[swpq_count], cx
  4219                              <1> ;       jz      short swpqs_10
  4220                              <1> ;		; esi = head + 4
  4221                              <1> ;		; edi = head
  4222                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4223                              <1> ;swpqs_10:
  4224                              <1> ;	mov	[edi], ecx ; 0
  4225                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4226                              <1> ;
  4227                              <1> ;swpqs_11:
  4228                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4229                              <1> ;	; Rotation (head -> tail)
  4230                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4231                              <1> ;	jz	short swpqs_10
  4232                              <1> ;		; esi = head + 4
  4233                              <1> ;		; edi = head
  4234                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4235                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4236                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4237                              <1> ;
  4238                              <1> ;	mov	cx, [swpq_count]
  4239                              <1> ;
  4240                              <1> ;swpqs_12:
  4241                              <1> ;	mov	esi, swap_queue ; head
  4242                              <1> ;       jmp     swpqs_7
  4243                              <1> ;
  4244                              <1> ;swpqs_13:
  4245                              <1> ;	dec	ecx
  4246                              <1> ;	mov	[swpq_count], cx
  4247                              <1> ;       jz      swpqs_5
  4248                              <1> ;	jmp	short swpqs_12
  4249                              <1> 
  4250                              <1> ; 24/12/2021
  4251                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4252                              <1> 
  4253                              <1> ;add_to_swap_queue:
  4254                              <1> 	; 20/02/2017
  4255                              <1> 	; 20/07/2015
  4256                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4257                              <1> 	;
  4258                              <1> 	; Adds new page to swap queue
  4259                              <1> 	; (page directories and page tables must not be added
  4260                              <1> 	; to swap queue)	
  4261                              <1> 	;
  4262                              <1> 	; INPUT ->
  4263                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4264                              <1> 	;	[u.uno]
  4265                              <1> 	;	20/02/2017
  4266                              <1> 	;	(Linear address = CORE + user's virtual address)
  4267                              <1> 	;
  4268                              <1> 	; OUTPUT ->
  4269                              <1> 	;	EAX = [swpq_count]
  4270                              <1> 	;	      (after the PTE has been added)
  4271                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4272                              <1> 	;	      the PTE could not be added.
  4273                              <1> 	;
  4274                              <1> 	; Modified Registers -> EAX
  4275                              <1> 	;
  4276                              <1> ;	push	ebx
  4277                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4278                              <1> ;	mov	bl, [u.uno] ; current process number
  4279                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4280                              <1> ;				 ; it is already on the queue
  4281                              <1> ;		; then add it to the tail of the queue
  4282                              <1> ;	movzx	eax, word [swpq_count]
  4283                              <1> ;	cmp	ax, 1024
  4284                              <1> ;	jb	short atsq_1
  4285                              <1> ;	sub	ax, ax
  4286                              <1> ;	pop	ebx
  4287                              <1> ;	retn
  4288                              <1> ;atsq_1:
  4289                              <1> ;	push	esi
  4290                              <1> ;	mov	esi, swap_queue
  4291                              <1> ;	and	ax, ax
  4292                              <1> ;	jz	short atsq_2
  4293                              <1> ;	shl	ax, 2	; convert to offset
  4294                              <1> ;	add	esi, eax
  4295                              <1> ;	shr	ax, 2
  4296                              <1> ;atsq_2:
  4297                              <1> ;	inc	ax
  4298                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4299                              <1> ;	mov	[swpq_count], ax
  4300                              <1> ;	pop	esi
  4301                              <1> ;	pop	ebx
  4302                              <1> ;	retn
  4303                              <1> 
  4304                              <1> ; 24/12/2021
  4305                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4306                              <1> 
  4307                              <1> ;unlink_swap_block:
  4308                              <1> 	; 15/09/2015
  4309                              <1> 	; 30/04/2015
  4310                              <1> 	; 18/04/2015
  4311                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4312                              <1> 	;
  4313                              <1> 	; INPUT -> 
  4314                              <1> 	;	EAX = swap disk/file offset address
  4315                              <1> 	;	      (bit 1 to bit 31)
  4316                              <1> 	; OUTPUT ->
  4317                              <1> 	;	[swpd_free] is increased
  4318                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4319                              <1> 	;
  4320                              <1> 	; Modified Registers -> EAX
  4321                              <1> 	;
  4322                              <1> ;	push	ebx
  4323                              <1> ;	push	edx
  4324                              <1> ;	;
  4325                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4326                              <1> ;				     ; 3 bits right
  4327                              <1> ;				     ; to get swap block/page number
  4328                              <1> ;	mov	edx, eax
  4329                              <1> ;	; 15/09/2015
  4330                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4331                              <1> ;				     ; (1 allocation bit = 1 page)
  4332                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4333                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4334                              <1> ;				     ; (to get 32 bit position)			
  4335                              <1> ;	;
  4336                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4337                              <1> ;	add	ebx, edx
  4338                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4339                              <1> ;				     ; (allocation bit position)	 
  4340                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4341                              <1> ;				     ; than the address in 'swpd_next' ?
  4342                              <1> ;				     ; (next/first free block value)		
  4343                              <1> ;	jnb	short uswpbl_1	     ; no	
  4344                              <1> ;	mov	[swpd_next], eax     ; yes	
  4345                              <1> ;uswpbl_1:
  4346                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4347                              <1> ;				     ; set relevant bit to 1.
  4348                              <1> ;				     ; set CF to the previous bit value	
  4349                              <1> ;	cmc			     ; complement carry flag	
  4350                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4351                              <1> ;				     ; if the block is already deallocated
  4352                              <1> ;				     ; before.	
  4353                              <1> ;       inc     dword [swpd_free]
  4354                              <1> ;uswpbl_2:
  4355                              <1> ;	pop	edx
  4356                              <1> ;	pop	ebx
  4357                              <1> ;	retn
  4358                              <1> 
  4359                              <1> ; 24/12/2021
  4360                              <1> ; ('link_swap_block' procedure call is disabled)
  4361                              <1> 
  4362                              <1> ;link_swap_block:
  4363                              <1> 	; 01/07/2015
  4364                              <1> 	; 18/04/2015
  4365                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4366                              <1> 	;
  4367                              <1> 	; INPUT -> none
  4368                              <1> 	;
  4369                              <1> 	; OUTPUT ->
  4370                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4371                              <1> 	;	      in sectors (corresponding 
  4372                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4373                              <1> 	;
  4374                              <1> 	;	CF = 1 and EAX = 0 
  4375                              <1> 	; 		   if there is not a free block to be allocated	
  4376                              <1> 	;
  4377                              <1> 	; Modified Registers -> none (except EAX)
  4378                              <1> 	;
  4379                              <1> 
  4380                              <1> ;	;mov	eax, [swpd_free]
  4381                              <1> ;	;and	eax, eax
  4382                              <1> ;	;jz	short out_of_swpspc
  4383                              <1> ;	;
  4384                              <1> ;	push	ebx
  4385                              <1> ;	push	ecx
  4386                              <1> ;	;
  4387                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4388                              <1> ;	mov	ecx, ebx
  4389                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4390                              <1> ;				 ; next_free_swap_block >> 5
  4391                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4392                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4393                              <1> ;lswbl_scan:
  4394                              <1> ;	cmp	ebx, ecx
  4395                              <1> ;	ja	short lswbl_notfound
  4396                              <1> ;	;
  4397                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4398                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4399                              <1> ;			   ; loads the destination with an index to
  4400                              <1> ;			   ; first set bit. (0 -> 31) 
  4401                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4402                              <1> ;	; 01/07/2015
  4403                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4404                              <1> ;			 ;
  4405                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4406                              <1> ;			 ;	  with value of 1 means 
  4407                              <1> ;			 ;	  the corresponding page is free 
  4408                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4409                              <1> ;	add	ebx, 4
  4410                              <1> ;			 ; We return back for searching next page block
  4411                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4412                              <1> ;			 ;	 we always will find at least 1 free block here.
  4413                              <1> ;	jmp    	short lswbl_scan
  4414                              <1> ;	;
  4415                              <1> ;lswbl_notfound:	
  4416                              <1> ;	sub	ecx, swap_alloc_table
  4417                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4418                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4419                              <1> ;	xor	eax, eax
  4420                              <1> ;	mov	[swpd_free], eax
  4421                              <1> ;	stc
  4422                              <1> ;lswbl_ok:
  4423                              <1> ;	pop	ecx
  4424                              <1> ;	pop	ebx
  4425                              <1> ;	retn
  4426                              <1> ;	;
  4427                              <1> ;;out_of_swpspc:
  4428                              <1> ;;	stc
  4429                              <1> ;;	retn
  4430                              <1> ;
  4431                              <1> ;lswbl_found:
  4432                              <1> ;	mov	ecx, ebx
  4433                              <1> ;	sub	ecx, swap_alloc_table
  4434                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4435                              <1> ;				 ; address/offset (to the next)
  4436                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4437                              <1> ;	;
  4438                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4439                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4440                              <1> ;				 ; in the destination.
  4441                              <1> ;				 ;
  4442                              <1> ;				 ; Reset the bit which is corresponding to the 
  4443                              <1> ;				 ; (just) allocated block.
  4444                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4445                              <1> ;	add	eax, ecx	 ; = block number
  4446                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4447                              <1> ;				 ; 1 block =  8 sectors
  4448                              <1> ;	;
  4449                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4450                              <1> ;	;
  4451                              <1> ;	; NOTE: The relevant page table entry will be updated
  4452                              <1> ;	;       according to this EAX value...
  4453                              <1> ;	;
  4454                              <1> ;	jmp	short lswbl_ok
  4455                              <1> 
  4456                              <1> ; 24/12/2021
  4457                              <1> ; ('logical_disk_read' procedure call is disabled)
  4458                              <1> 
  4459                              <1> ;logical_disk_read:
  4460                              <1> 	; 20/07/2015
  4461                              <1> 	; 09/03/2015 (temporary code here)
  4462                              <1> 	;
  4463                              <1> 	; INPUT ->
  4464                              <1> 	; 	ESI = Logical disk description table address
  4465                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4466                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4467                              <1> 	; 	ECX = Sector count
  4468                              <1> 	;
  4469                              <1> 	;
  4470                              <1> ;	retn
  4471                              <1> 
  4472                              <1> ; 24/12/2021
  4473                              <1> ; ('logical_disk_write' procedure call is disabled)
  4474                              <1> 
  4475                              <1> ;logical_disk_write:
  4476                              <1> 	; 20/07/2015
  4477                              <1> 	; 09/03/2015 (temporary code here)
  4478                              <1> 	;
  4479                              <1> 	; INPUT ->
  4480                              <1> 	; 	ESI = Logical disk description table address
  4481                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4482                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4483                              <1> 	; 	ECX = Sector count
  4484                              <1> 	;
  4485                              <1> ;	retn
  4486                              <1> 
  4487                              <1> get_physical_addr:
  4488                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4489                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4490                              <1> 	; 18/10/2015
  4491                              <1> 	; 29/07/2015
  4492                              <1> 	; 20/07/2015
  4493                              <1> 	; 04/06/2015
  4494                              <1> 	; 20/05/2015
  4495                              <1> 	; 28/04/2015
  4496                              <1> 	; 18/04/2015
  4497                              <1> 	; Get physical address
  4498                              <1> 	;     (allocates a new page for user if it is not present)
  4499                              <1> 	;	
  4500                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4501                              <1> 	; (buffer) address to physical address (of the buffer).)
  4502                              <1> 	; ('sys write', 'sys read' system calls...)
  4503                              <1> 	;
  4504                              <1> 	; INPUT ->
  4505                              <1> 	;	EBX = virtual address
  4506                              <1> 	;	u.pgdir = page directory (physical) address
  4507                              <1> 	;
  4508                              <1> 	; OUTPUT ->
  4509                              <1> 	;	EAX = physical address 
  4510                              <1> 	;	EBX = linear address	
  4511                              <1> 	;	EDX = physical address of the page frame
  4512                              <1> 	;	      (with attribute bits)
  4513                              <1> 	;	ECX = byte count within the page frame
  4514                              <1> 	;
  4515                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4516                              <1> 	;
  4517                              <1> 
  4518                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4519 000031C0 A1[FF6E0000]        <1> 	mov	eax, [u.pgdir]
  4520                              <1> 
  4521                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4522                              <1> 	
  4523 000031C5 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4524                              <1> 	;
  4525                              <1> 	;mov	eax, [u.pgdir]
  4526 000031CB E816FDFFFF          <1> 	call	get_pte
  4527                              <1> 		; EDX = Page table entry address (if CF=0)
  4528                              <1> 	        ;       Page directory entry address (if CF=1)
  4529                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4530                              <1> 		; EAX = Page table entry value (page address)
  4531                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4532 000031D0 731C                <1> 	jnc	short gpa_1
  4533                              <1> 	;
  4534 000031D2 E8FDFBFFFF          <1> 	call	allocate_page
  4535 000031D7 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4536                              <1> gpa_0:
  4537 000031D9 E867FCFFFF          <1> 	call 	clear_page
  4538                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4539 000031DE 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4540                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4541                              <1> 			   ; (user, writable, present page)	
  4542 000031E0 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4543 000031E2 A1[FF6E0000]        <1> 	mov	eax, [u.pgdir]	
  4544 000031E7 E8FAFCFFFF          <1> 	call	get_pte
  4545 000031EC 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4546                              <1> gpa_1:
  4547                              <1> 	; EAX = PTE value, EDX = PTE address
  4548 000031EE A801                <1> 	test 	al, PTE_A_PRESENT
  4549 000031F0 750A                <1> 	jnz	short gpa_3
  4550 000031F2 09C0                <1> 	or	eax, eax
  4551 000031F4 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4552                              <1> 
  4553                              <1> ; 24/12/2021
  4554                              <1> ; ('reload_page' procedure call is disabled)
  4555 000031F6 EB2C                <1> 	jmp	short gpa_im_err
  4556                              <1> 
  4557                              <1> 	; 20/07/2015
  4558                              <1> ;	push	ebp
  4559                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4560                              <1> ;	; reload swapped page
  4561                              <1> ;	call	reload_page ; 28/04/2015
  4562                              <1> ;	pop	ebp
  4563                              <1> ;	jc	short gpa_retn
  4564                              <1> gpa_2:
  4565                              <1> ; 24/12/2021
  4566                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4567                              <1> 
  4568                              <1> 	; 20/07/2015
  4569                              <1> 	; 20/05/2015
  4570                              <1> 	; add this page to swap queue
  4571                              <1> ;	push	eax 
  4572                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4573                              <1> ;	call 	add_to_swap_queue
  4574                              <1> ;	pop	eax
  4575                              <1> 		; PTE address in EDX
  4576                              <1> 		; virtual address in EBX
  4577                              <1> 	; EAX = memory page address
  4578 000031F8 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4579                              <1> 				  ; present flag, bit 0 = 1
  4580                              <1> 				  ; user flag, bit 2 = 1	
  4581                              <1> 				  ; writable flag, bit 1 = 1
  4582 000031FA 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4583                              <1> gpa_3:
  4584                              <1> 	; 18/10/2015
  4585 000031FC 89D9                <1> 	mov	ecx, ebx
  4586 000031FE 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4587 00003204 89C2                <1> 	mov 	edx, eax
  4588 00003206 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4589 0000320A 01C8                <1> 	add	eax, ecx
  4590 0000320C F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4591 0000320E 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4592 00003214 F8                  <1> 	clc
  4593                              <1> gpa_retn:
  4594 00003215 C3                  <1> 	retn	
  4595                              <1> gpa_4:	
  4596 00003216 E8B9FBFFFF          <1> 	call	allocate_page
  4597 0000321B 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4598 0000321D E823FCFFFF          <1> 	call	clear_page
  4599 00003222 EBD4                <1> 	jmp	short gpa_2
  4600                              <1> 
  4601                              <1> gpa_im_err:	
  4602 00003224 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4603                              <1> 				  ; Major error = 0 (No protection fault)	
  4604 00003229 C3                  <1> 	retn
  4605                              <1> 
  4606                              <1> ; 24/12/2021
  4607                              <1> ; ('reload_page' procedure call is disabled)
  4608                              <1> 
  4609                              <1> ;reload_page:
  4610                              <1> 	; 20/07/2015
  4611                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4612                              <1> 	;
  4613                              <1> 	; Reload (Restore) swapped page at memory
  4614                              <1> 	;
  4615                              <1> 	; INPUT -> 
  4616                              <1> 	;	EBP = Virtual (linear) memory address
  4617                              <1> 	;	EAX = PTE value (swap disk sector address)
  4618                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4619                              <1> 	; OUTPUT ->
  4620                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4621                              <1> 	;
  4622                              <1> 	;	CF = 1 and EAX = error code
  4623                              <1> 	;
  4624                              <1> 	; Modified Registers -> none (except EAX)
  4625                              <1> 	;
  4626                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4627                              <1> ;	push	ebx      ;
  4628                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4629                              <1> ;	call	allocate_page
  4630                              <1> ;	jc	short rlp_im_err
  4631                              <1> ;	xchg 	eax, ebx	
  4632                              <1> ;	; EBX = Physical memory (page) address
  4633                              <1> ;	; EAX = Swap disk (offset) address
  4634                              <1> ;	; EBP = Virtual (linear) memory address
  4635                              <1> ;	call	swap_in
  4636                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4637                              <1> ;	mov	eax, ebx	
  4638                              <1> ;rlp_retn:
  4639                              <1> ;	pop	ebx
  4640                              <1> ;	retn
  4641                              <1> ;	
  4642                              <1> ;rlp_im_err:	
  4643                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4644                              <1> ;				  ; Major error = 0 (No protection fault)	
  4645                              <1> ;	jmp	short rlp_retn
  4646                              <1> ;
  4647                              <1> ;rlp_swp_err:
  4648                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4649                              <1> ;	jmp	short rlp_retn
  4650                              <1> 
  4651                              <1> copy_page_dir:
  4652                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4653                              <1> 	; 19/09/2015
  4654                              <1> 	; temporary - 07/09/2015
  4655                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4656                              <1> 	;
  4657                              <1> 	; INPUT -> 
  4658                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4659                              <1> 	;		    page directory.
  4660                              <1> 	; OUTPUT ->
  4661                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4662                              <1> 	;	       page directory.
  4663                              <1> 	;	(New page directory with new page table entries.)
  4664                              <1> 	;	(New page tables with read only copies of the parent's
  4665                              <1> 	;	pages.)
  4666                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4667                              <1> 	;
  4668                              <1> 	; Modified Registers -> none (except EAX)
  4669                              <1> 	;
  4670 0000322A E8A5FBFFFF          <1> 	call	allocate_page
  4671 0000322F 723E                <1> 	jc	short cpd_err
  4672                              <1> 	;
  4673 00003231 55                  <1> 	push	ebp ; 20/07/2015
  4674 00003232 56                  <1> 	push	esi
  4675 00003233 57                  <1> 	push	edi
  4676 00003234 53                  <1> 	push	ebx
  4677 00003235 51                  <1> 	push	ecx
  4678 00003236 8B35[FF6E0000]      <1> 	mov	esi, [u.pgdir]
  4679 0000323C 89C7                <1> 	mov	edi, eax
  4680 0000323E 50                  <1> 	push	eax ; save child's page directory address
  4681                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4682                              <1> 	; (use same system space for all user page tables) 
  4683 0000323F A5                  <1> 	movsd
  4684 00003240 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4685 00003245 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4686                              <1> cpd_0:	
  4687 0000324A AD                  <1> 	lodsd
  4688                              <1> 	;or	eax, eax
  4689                              <1>         ;jnz	short cpd_1
  4690 0000324B A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4691 0000324D 7508                <1> 	jnz	short cpd_1
  4692                              <1>  	; (virtual address at the end of the page table)	
  4693 0000324F 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4694 00003255 EB0F                <1> 	jmp	short cpd_2
  4695                              <1> cpd_1:	
  4696 00003257 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4697 0000325B 89C3                <1> 	mov	ebx, eax
  4698                              <1> 	; EBX = Parent's page table address
  4699 0000325D E81F000000          <1> 	call	copy_page_table
  4700 00003262 720C                <1> 	jc	short cpd_p_err
  4701                              <1> 	; EAX = Child's page table address
  4702 00003264 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4703                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4704                              <1> 			 ; (present, writable, user)
  4705                              <1> cpd_2:
  4706 00003266 AB                  <1> 	stosd
  4707 00003267 E2E1                <1> 	loop	cpd_0
  4708                              <1> 	;
  4709 00003269 58                  <1> 	pop	eax  ; restore child's page directory address
  4710                              <1> cpd_3:
  4711 0000326A 59                  <1> 	pop	ecx
  4712 0000326B 5B                  <1> 	pop	ebx
  4713 0000326C 5F                  <1> 	pop	edi
  4714 0000326D 5E                  <1> 	pop	esi
  4715 0000326E 5D                  <1> 	pop	ebp
  4716                              <1> cpd_err:
  4717 0000326F C3                  <1> 	retn
  4718                              <1> cpd_p_err:
  4719                              <1> 	; release the allocated pages missing (recover free space)
  4720 00003270 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4721 00003271 8B1D[FF6E0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4722 00003277 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4723 0000327C 29C0                <1> 	sub	eax, eax ; 0
  4724 0000327E F9                  <1> 	stc
  4725 0000327F EBE9                <1> 	jmp	short cpd_3	
  4726                              <1> 
  4727                              <1> copy_page_table:
  4728                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4729                              <1> 	; 19/09/2015
  4730                              <1> 	; temporary - 07/09/2015
  4731                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4732                              <1> 	;
  4733                              <1> 	; INPUT -> 
  4734                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4735                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4736                              <1> 	; OUTPUT ->
  4737                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4738                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4739                              <1> 	;	CF = 1 -> error 
  4740                              <1> 	;
  4741                              <1> 	; Modified Registers -> EBP (except EAX)
  4742                              <1> 	;
  4743 00003281 E84EFBFFFF          <1> 	call	allocate_page
  4744 00003286 7244                <1> 	jc	short cpt_err
  4745                              <1> 	;
  4746 00003288 50                  <1> 	push	eax ; *
  4747                              <1> 	;push 	ebx
  4748 00003289 56                  <1> 	push	esi
  4749 0000328A 57                  <1> 	push	edi
  4750 0000328B 52                  <1> 	push	edx
  4751 0000328C 51                  <1> 	push	ecx
  4752                              <1> 	;
  4753 0000328D 89DE                <1> 	mov	esi, ebx
  4754 0000328F 89C7                <1> 	mov	edi, eax
  4755 00003291 89C2                <1> 	mov	edx, eax
  4756 00003293 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4757                              <1> cpt_0:
  4758 00003299 AD                  <1> 	lodsd
  4759 0000329A A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4760                              <1> 	;jnz	short cpt_1 (*)
  4761                              <1> 	; 24/12/2021
  4762                              <1> 	;and	eax, eax (*)
  4763 0000329C 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4764                              <1> 	
  4765                              <1> ; 24/12/2021
  4766                              <1> ; ('reload_page' procedure call is disabled)
  4767                              <1> ;
  4768                              <1> ;	; ebp = virtual (linear) address of the memory page
  4769                              <1> ;	call	reload_page ; 28/04/2015
  4770                              <1> ;	jc	short cpt_p_err
  4771                              <1> cpt_1:
  4772 0000329E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4773 000032A2 89C1                <1> 	mov	ecx, eax
  4774                              <1> 	; Allocate a new page for the child process
  4775 000032A4 E82BFBFFFF          <1> 	call	allocate_page
  4776 000032A9 721C                <1> 	jc	short cpt_p_err
  4777 000032AB 57                  <1> 	push	edi
  4778 000032AC 56                  <1> 	push	esi
  4779 000032AD 89CE                <1> 	mov	esi, ecx
  4780 000032AF 89C7                <1> 	mov	edi, eax
  4781 000032B1 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4782 000032B6 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4783 000032B8 5E                  <1> 	pop	esi
  4784 000032B9 5F                  <1> 	pop	edi
  4785                              <1> 	; 
  4786                              <1> ; 24/12/2021
  4787                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4788                              <1> ;
  4789                              <1> ;	push	ebx
  4790                              <1> ;	push	eax
  4791                              <1> ;	mov	ebx, ebp
  4792                              <1> ;	; ebx = virtual address of the memory page
  4793                              <1> ;	call	add_to_swap_queue
  4794                              <1> ;	pop	eax
  4795                              <1> ;	pop	ebx
  4796                              <1> 	;
  4797                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4798 000032BA 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4799                              <1> cpt_2:
  4800 000032BC AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4801                              <1> 	;
  4802 000032BD 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4803                              <1> 	;
  4804 000032C3 39D7                <1> 	cmp	edi, edx
  4805 000032C5 72D2                <1> 	jb	short cpt_0
  4806                              <1> cpt_p_err:
  4807 000032C7 59                  <1> 	pop	ecx
  4808 000032C8 5A                  <1> 	pop	edx
  4809 000032C9 5F                  <1> 	pop	edi
  4810 000032CA 5E                  <1> 	pop	esi
  4811                              <1> 	;pop	ebx
  4812 000032CB 58                  <1> 	pop	eax ; *
  4813                              <1> cpt_err:
  4814 000032CC C3                  <1> 	retn
  4815                              <1> 
  4816                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4817                              <1> 
  4818                              <1> ;; Data:
  4819                              <1> 
  4820                              <1> ; 09/03/2015
  4821                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4822                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4823                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4824                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4825                              <1> ;swpd_next:  dd 0 ; next free page block
  4826                              <1> ;swpd_last:  dd 0 ; last swap page block
  2044                                  %include 'sysdefs.inc' ; 09/03/2015
  2045                              <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC
  2046                              <1> ; Last Modification: 12/02/2022
  2047                              <1> ;
  2048                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2049                              <1> ; (Modified from 
  2050                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2051                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2052                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2053                              <1> ; ----------------------------------------------------------------------------
  2054                              <1> ;
  2055                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2056                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2057                              <1> ; <Bell Laboratories (17/3/1972)>
  2058                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2059                              <1> ;
  2060                              <1> ; ****************************************************************************
  2061                              <1> 
  2062                              <1> nproc 	equ	16  ; number of processes
  2063                              <1> nfiles 	equ	50
  2064                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2065                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2066                              <1> 
  2067                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2068                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2069                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2070                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2071                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2072                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2073                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2074                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2075                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2076                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2077                              <1> 	; '/core' dump file size = 32768 bytes
  2078                              <1>  
  2079                              <1> ; 08/03/2014 
  2080                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2081                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2082                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2083                              <1> 
  2084                              <1> ; 30/08/2013
  2085                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2086                              <1> 
  2087                              <1> ; 05/02/2014
  2088                              <1> ; process status
  2089                              <1> ;SFREE 	equ 0
  2090                              <1> ;SRUN	equ 1
  2091                              <1> ;SWAIT	equ 2
  2092                              <1> ;SZOMB	equ 3
  2093                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2094                              <1> 
  2095                              <1> ; 09/03/2015
  2096                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2097                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2098                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2099                              <1> 
  2100                              <1> ; 17/09/2015
  2101                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2102                              <1> 
  2103                              <1> ; 21/09/2015 (36) 
  2104                              <1> ; 01/07/2015 (35)
  2105                              <1> ; 14/07/2013 (0-34)
  2106                              <1> ; UNIX v1 system calls
  2107                              <1> _rele 	equ 0
  2108                              <1> _exit 	equ 1
  2109                              <1> _fork 	equ 2
  2110                              <1> _read 	equ 3
  2111                              <1> _write	equ 4
  2112                              <1> _open	equ 5
  2113                              <1> _close 	equ 6
  2114                              <1> _wait 	equ 7
  2115                              <1> _creat 	equ 8
  2116                              <1> _link 	equ 9
  2117                              <1> _unlink	equ 10
  2118                              <1> _exec	equ 11
  2119                              <1> _chdir	equ 12
  2120                              <1> _time 	equ 13
  2121                              <1> _mkdir 	equ 14
  2122                              <1> _chmod	equ 15
  2123                              <1> _chown	equ 16
  2124                              <1> _break	equ 17
  2125                              <1> _stat	equ 18
  2126                              <1> _seek	equ 19
  2127                              <1> _tell 	equ 20
  2128                              <1> _mount	equ 21
  2129                              <1> _umount	equ 22
  2130                              <1> _setuid	equ 23
  2131                              <1> _getuid	equ 24
  2132                              <1> _stime	equ 25
  2133                              <1> _quit	equ 26	
  2134                              <1> _intr	equ 27
  2135                              <1> _fstat	equ 28
  2136                              <1> _emt 	equ 29
  2137                              <1> _mdate 	equ 30
  2138                              <1> _stty 	equ 31
  2139                              <1> _gtty	equ 32
  2140                              <1> _ilgins	equ 33
  2141                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2142                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2143                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2144                              <1> 
  2145                              <1> %macro sys 1-4
  2146                              <1>     ; 13/04/2015
  2147                              <1>     ; Retro UNIX 386 v1 system call.		
  2148                              <1>     mov eax, %1
  2149                              <1>     %if %0 >= 2   
  2150                              <1>         mov ebx, %2
  2151                              <1>         %if %0 >= 3    
  2152                              <1>             mov ecx, %3
  2153                              <1>             %if %0 = 4
  2154                              <1>                mov edx, %4   
  2155                              <1>             %endif
  2156                              <1>         %endif
  2157                              <1>     %endif
  2158                              <1>     int 30h	   
  2159                              <1> %endmacro
  2160                              <1> 
  2161                              <1> ; 13/05/2015 - ERROR CODES
  2162                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2163                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2164                              <1> ; 14/05/2015
  2165                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2166                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2167                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2168                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2169                              <1> ; 16/05/2015		
  2170                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2171                              <1> ; 18/05/2015
  2172                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2173                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2174                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2175                              <1> ; 07/06/2015
  2176                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2177                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2178                              <1> ; 09/06/2015
  2179                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2180                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2181                              <1> ; 16/06/2015
  2182                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2183                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2184                              <1> ; 22/06/2015
  2185                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2186                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2187                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2188                              <1> ; 23/06/2015
  2189                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2190                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2191                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2192                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2193                              <1> ; 27/06/2015
  2194                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2195                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2196                              <1> ; 29/06/2015
  2197                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2198                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2199                              <1> ; 12/02/2022 
  2200                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2201                              <1> ; 10/10/2016
  2202                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2203                              <1> ; 18/05/2016
  2204                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2205                              <1> ; 15/10/2016
  2206                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2207                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2208                              <1> ; 16/10/2016
  2209                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2210                              <1> ; 08/02/2022
  2211                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error	
  2212                              <1> 
  2213                              <1> ; 26/08/2015
  2214                              <1> ; 24/07/2015
  2215                              <1> ; 24/06/2015
  2216                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2217                              <1> ; 01/07/2015
  2218                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2219                              <1> ;	 					 		
  2045                                  %include 'u0.s'        ; 15/03/2015
  2046                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYS0.INC
  2047                              <1> ; Last Modification: 27/02/2022
  2048                              <1> ; ----------------------------------------------------------------------------
  2049                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2050                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2051                              <1> ;
  2052                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2053                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2054                              <1> ; <Bell Laboratories (17/3/1972)>
  2055                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2056                              <1> ;
  2057                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2058                              <1> ;
  2059                              <1> ; ****************************************************************************
  2060                              <1> ; 21/11/2015
  2061                              <1> 
  2062                              <1> sys_init:
  2063                              <1> 	; 27/02/2022
  2064                              <1> 	; 23/02/2022
  2065                              <1> 	; 04/02/2022
  2066                              <1> 	; 18/10/2015
  2067                              <1> 	; 28/08/2015
  2068                              <1> 	; 24/08/2015
  2069                              <1> 	; 14/08/2015
  2070                              <1> 	; 24/07/2015 
  2071                              <1> 	; 02/07/2015
  2072                              <1> 	; 01/07/2015
  2073                              <1> 	; 23/06/2015
  2074                              <1> 	; 15/04/2015
  2075                              <1> 	; 13/04/2015
  2076                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2077                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2078                              <1> 	;
  2079                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2080                              <1> 	;
  2081                              <1> 	; 14/02/2014
  2082                              <1> 	; 14/07/2013
  2083                              <1> 	;;mov	ax, 41
  2084                              <1> 	; 27/02/2022
  2085                              <1> 	;xor	eax, eax
  2086                              <1> 	;mov	al, 41
  2087                              <1> 	;mov	[rootdir], ax
  2088                              <1> 	;mov	[u.cdir], ax
  2089                              <1> 	;;and	al, 1 ; 15/04/2015
  2090                              <1> 	;inc	al  ; ax = 1
  2091 000032CD B001                <1> 	mov	al, 1
  2092 000032CF A2[F56E0000]        <1> 	mov	[u.uno], al
  2093                              <1> 	;mov	[mpid], ax
  2094                              <1> 	;mov	[p.pid], ax
  2095 000032D4 A2[986E0000]        <1> 	mov	[mpid], al
  2096 000032D9 A2[C86B0000]        <1> 	mov	[p.pid], al	
  2097 000032DE A2[286C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2098                              <1> 	; 27/02/2022
  2099 000032E3 B029                <1> 	mov	al, 41
  2100                              <1> 	;mov	[rootdir], ax
  2101                              <1> 	;mov	[u.cdir], ax
  2102 000032E5 A2[9A6E0000]        <1> 	mov	[rootdir], al
  2103 000032EA A2[B06E0000]        <1> 	mov	[u.cdir], al
  2104                              <1> 	;
  2105                              <1> 	; 23/02/2022
  2106                              <1>  	;call	epoch
  2107                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2108                              <1> 	; 17/07/2013
  2109 000032EF E896060000          <1> 	call 	bf_init ; buffer initialization
  2110                              <1> 	; 23/02/2022
  2111                              <1> 	; (save sysinit time on sb0)
  2112 000032F4 E830030000          <1> 	call	epoch
  2113 000032F9 A3[F07C0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2114                              <1> 	; 23/06/2015
  2115 000032FE E8D1FAFFFF          <1> 	call	allocate_page
  2116                              <1> 	;;jc	error
  2117                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2118                              <1> 	; 04/02/2022
  2119 00003303 7305                <1> 	jnc	short sysinit_1
  2120 00003305 E990000000          <1> 	jmp	panic
  2121                              <1> sysinit_1:
  2122 0000330A A3[F66E0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2123 0000330F A3[386C0000]        <1> 	mov	[p.upage], eax
  2124                              <1> 	;
  2125 00003314 E82CFBFFFF          <1> 	call	clear_page
  2126                              <1> 	;
  2127                              <1> 	; 14/08/2015
  2128 00003319 FA                  <1> 	cli
  2129                              <1> 	; 14/03/2015
  2130                              <1> 	; 17/01/2014
  2131 0000331A E8D7010000          <1> 	call	sp_init ; serial port initialization
  2132                              <1> 	; 14/08/2015
  2133 0000331F FB                  <1> 	sti
  2134                              <1> 	;
  2135                              <1> 	; 30/06/2015
  2136                              <1> 	;mov	esi, kernel_init_ok_msg
  2137                              <1> 	;call 	print_msg
  2138                              <1> 	;
  2139 00003320 30DB                <1> 	xor	bl, bl ; video page 0
  2140                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2141 00003322 E84B0F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2142 00003327 FEC3                <1> 	inc	bl
  2143 00003329 80FB08              <1> 	cmp	bl, 8
  2144 0000332C 72F4                <1> 	jb	short vp_clr_nxt
  2145                              <1> 	;
  2146                              <1> 	; 24/07/2015
  2147                              <1> 	;push	KDATA
  2148                              <1>         ;push	esp
  2149                              <1> 	;mov	[tss.esp0], esp
  2150                              <1>         ;mov	word [tss.ss0], KDATA
  2151                              <1> 	;
  2152                              <1> 	; 27/02/2022
  2153                              <1> 	; 24/08/2015
  2154                              <1> 	;; temporary (01/07/2015)
  2155                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2156                              <1> 			       ; it is not needed here !
  2157                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2158 0000332E FE0D[A16E0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2159                              <1> 			      ; 0 = executing a system call
  2160                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2161                              <1> 	;
  2162                              <1> 	;;; 06/08/2015
  2163                              <1> 	;;;call	getch ; wait for a key stroke
  2164                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2165                              <1> ;;sys_init_msg_wait:
  2166                              <1> ;;	push 	ecx
  2167                              <1> ;;	mov	al, 1
  2168                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2169                              <1> ;;	call	getc_n
  2170                              <1> ;;	pop	ecx
  2171                              <1> ;;	jnz	short sys_init_msg_ok
  2172                              <1> ;;	loop	sys_init_msg_wait
  2173                              <1> 	;
  2174                              <1> ;;sys_init_msg_ok:
  2175                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2176 00003334 6A10                <1> 	push	KDATA ; ss
  2177 00003336 54                  <1> 	push	esp
  2178 00003337 9C                  <1> 	pushfd
  2179 00003338 6A08                <1> 	push	KCODE ; cs
  2180 0000333A 68[6E330000]        <1> 	push	init_exec ; eip
  2181 0000333F 8925[A46E0000]      <1> 	mov	[u.sp], esp
  2182 00003345 1E                  <1> 	push	ds
  2183 00003346 06                  <1> 	push	es
  2184 00003347 0FA0                <1> 	push	fs
  2185 00003349 0FA8                <1> 	push	gs	
  2186 0000334B 60                  <1> 	pushad
  2187 0000334C 8925[A86E0000]      <1> 	mov	[u.usp], esp
  2188 00003352 E8641B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2189                              <1> 		      ; and interrupt return components (for IRET)
  2190 00003357 61                  <1> 	popad
  2191 00003358 6658                <1> 	pop	ax ; gs
  2192 0000335A 6658                <1> 	pop	ax ; fs
  2193 0000335C 6658                <1> 	pop	ax ; es
  2194 0000335E 6658                <1> 	pop	ax ; ds	
  2195 00003360 58                  <1> 	pop	eax ; eip (init_exec)
  2196 00003361 6658                <1> 	pop	ax ; cs (KCODE)
  2197 00003363 58                  <1> 	pop	eax ; E-FLAGS
  2198 00003364 58                  <1> 	pop	eax ; esp
  2199 00003365 6658                <1> 	pop	ax ; ss (KDATA)
  2200                              <1> 	;
  2201 00003367 31C0                <1> 	xor	eax, eax ; 0
  2202 00003369 A3[036F0000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2203                              <1> 	;
  2204                              <1> 	; 02/07/2015
  2205                              <1> 	; [u.pgdir ] = [k_page_dir]
  2206                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2207                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2208                              <1> init_exec:
  2209                              <1> 	; 13/03/2013
  2210                              <1> 	; 24/07/2013
  2211 0000336E BB[90330000]        <1> 	mov	ebx, init_file
  2212 00003373 B9[88330000]        <1> 	mov	ecx, init_argp
  2213                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2214                              <1> 	; ECX contains address of argument list pointer
  2215                              <1> 	;
  2216                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2217                              <1> 			      ; 0 = executing a system call
  2218                              <1> 	sys	_exec  ; execute file
  2146                              <2> 
  2147                              <2> 
  2148 00003378 B80B000000          <2>  mov eax, %1
  2149                              <2>  %if %0 >= 2
  2150                              <2>  mov ebx, %2
  2151                              <2>  %if %0 >= 3
  2152                              <2>  mov ecx, %3
  2153                              <2>  %if %0 = 4
  2154                              <2>  mov edx, %4
  2155                              <2>  %endif
  2156                              <2>  %endif
  2157                              <2>  %endif
  2158 0000337D CD30                <2>  int 30h
  2219 0000337F 7319                <1> 	jnc	short panic
  2220                              <1> 	;
  2221 00003381 BE[FA670000]        <1> 	mov	esi, etc_init_err_msg
  2222                              <1> 	; 27/02/2022
  2223                              <1> 	;call 	print_msg
  2224 00003386 EB17                <1> 	jmp	short key_to_reboot
  2225                              <1> 
  2226                              <1> ;align 4
  2227                              <1> init_argp:
  2228 00003388 [90330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2229                              <1> init_file:
  2230                              <1> 	; 24/08/2015
  2231 00003390 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2231 00003399 00                  <1>
  2232                              <1> panic:
  2233                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2234                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2235 0000339A BE[DF670000]        <1> 	mov 	esi, panic_msg
  2236                              <1> key_to_reboot: ; 27/02/2022
  2237 0000339F E819000000          <1> 	call 	print_msg
  2238                              <1> ;key_to_reboot:
  2239                              <1> 	; 15/11/2015
  2240 000033A4 E8CC2B0000          <1> 	call 	getch 
  2241                              <1> 		; wait for a character from the current tty
  2242                              <1> 	;
  2243 000033A9 B00A                <1> 	mov	al, 0Ah
  2244 000033AB 8A1D[166B0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2245 000033B1 B407                <1> 	mov	ah, 07h ; Black background, 
  2246                              <1> 			; light gray forecolor
  2247 000033B3 E827E0FFFF          <1> 	call 	write_tty
  2248 000033B8 E9C2DCFFFF          <1> 	jmp	cpu_reset 
  2249                              <1> 
  2250                              <1> print_msg:
  2251                              <1> 	; 01/07/2015
  2252                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2253                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2254                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2255                              <1> 	;
  2256                              <1> 	;
  2257 000033BD AC                  <1> 	lodsb
  2258                              <1> pmsg1:
  2259 000033BE 56                  <1> 	push 	esi
  2260 000033BF 0FB61D[166B0000]    <1> 	movzx	ebx, byte [ptty]
  2261 000033C6 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2262 000033C8 E812E0FFFF          <1> 	call 	write_tty
  2263 000033CD 5E                  <1> 	pop	esi
  2264 000033CE AC                  <1> 	lodsb
  2265 000033CF 20C0                <1> 	and 	al, al
  2266 000033D1 75EB                <1> 	jnz 	short pmsg1
  2267 000033D3 C3                  <1> 	retn
  2268                              <1> 	
  2269                              <1> ctrlbrk:
  2270                              <1> 	; 04/02/2022
  2271                              <1> 	; 01/02/2022
  2272                              <1> 	; 12/11/2015
  2273                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2274                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2275                              <1> 	;
  2276                              <1> 	; INT 1Bh (control+break) handler
  2277                              <1> 	;
  2278                              <1>       	; Retro Unix 8086 v1 feature only!
  2279                              <1>       	;
  2280 000033D4 66833D[EA6E0000]00  <1> 	cmp 	word [u.intr], 0
  2281 000033DC 764B                <1> 	jna 	short cbrk4
  2282                              <1> cbrk0:
  2283                              <1> 	; 12/11/2015
  2284                              <1> 	; 06/12/2013
  2285 000033DE 66833D[EC6E0000]00  <1> 	cmp 	word [u.quit], 0
  2286 000033E6 7441                <1> 	jz	short cbrk4
  2287                              <1> 	;
  2288                              <1> 	; 20/09/2013	
  2289                              <1> 	;push 	ax
  2290                              <1> 	; 01/02/2022
  2291 000033E8 50                  <1> 	push	eax
  2292                              <1> 
  2293                              <1> 	; 04/02/2022
  2294                              <1> 	; (repetitive ctrl+brk check) 
  2295 000033E9 66A1[EC6E0000]      <1> 	mov	ax, [u.quit]
  2296 000033EF 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2297 000033F1 7435                <1> 	jz	short cbrk3
  2298                              <1> 
  2299                              <1> 	; 20/09/2013
  2300 000033F3 A0[166B0000]        <1> 	mov	al, [ptty]
  2301                              <1> 	;
  2302                              <1> 	; 12/11/2015
  2303                              <1> 	;
  2304                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2305                              <1> 	; or ctrl+break from console (pseudo) tty
  2306                              <1> 	; (!redirection!)
  2307                              <1> 	;
  2308 000033F8 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2309 000033FA 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2310                              <1> 	;	
  2311                              <1> 	; Serial port interrupt handler sets [ptty]
  2312                              <1> 	; to the port's tty number (as temporary).
  2313                              <1> 	;
  2314                              <1> 	; If active process is using a stdin or 
  2315                              <1> 	; stdout redirection (by the shell),
  2316                              <1>         ; console tty keyboard must be available
  2317                              <1> 	; to terminate running process,
  2318                              <1> 	; in order to prevent a deadlock. 
  2319                              <1> 	;
  2320 000033FC 52                  <1> 	push	edx
  2321 000033FD 0FB615[F56E0000]    <1> 	movzx	edx, byte [u.uno]
  2322 00003404 3A82[076C0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2323 0000340A 5A                  <1> 	pop	edx
  2324 0000340B 7412                <1> 	je	short cbrk2
  2325                              <1> cbrk1:
  2326 0000340D FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2327                              <1> 	; 06/12/2013
  2328 0000340F 3A05[DC6E0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2329 00003415 7408                <1> 	je	short cbrk2	
  2330 00003417 3A05[DD6E0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2331 0000341D 7509                <1> 	jne	short cbrk3	
  2332                              <1> cbrk2:
  2333                              <1> 	;; 06/12/2013
  2334                              <1> 	;mov	ax, [u.quit]
  2335                              <1> 	;and	ax, ax
  2336                              <1> 	;jz	short cbrk3
  2337                              <1> 	;
  2338                              <1> 	;xor	ax, ax ; 0
  2339                              <1> 	;dec	ax
  2340                              <1> 	; 01/02/2022
  2341 0000341F 31C0                <1> 	xor	eax, eax ; 0
  2342 00003421 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2343                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2344 00003422 66A3[EC6E0000]      <1> 	mov	[u.quit], ax
  2345                              <1> cbrk3:
  2346                              <1> 	;pop	ax
  2347                              <1> 	; 01/02/2022
  2348 00003428 58                  <1> 	pop	eax
  2349                              <1> cbrk4:
  2350 00003429 C3                  <1> 	retn
  2351                              <1> 
  2352                              <1> com2_int:
  2353                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2354                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2355                              <1> 	; 07/11/2015 
  2356                              <1> 	; 24/10/2015
  2357                              <1> 	; 23/10/2015
  2358                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2359                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2360                              <1> 	; < serial port 2 interrupt handler >
  2361                              <1> 	;
  2362 0000342A 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2363                              <1> 	;;push	eax
  2364                              <1> 	; 08/01/2022
  2365 0000342D 29C0                <1> 	sub	eax, eax
  2366 0000342F B009                <1> 	mov	al, 9
  2367                              <1> 	;mov	ax, 9
  2368 00003431 EB07                <1> 	jmp	short comm_int
  2369                              <1> com1_int:
  2370                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2371                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2372                              <1> 	; 07/11/2015
  2373                              <1> 	; 24/10/2015
  2374 00003433 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2375                              <1> 	; 23/10/2015
  2376                              <1> 	;push	eax
  2377                              <1> 	; 08/01/2022
  2378 00003436 29C0                <1> 	sub	eax, eax
  2379 00003438 B008                <1> 	mov	al, 8
  2380                              <1> 	;mov	ax, 8
  2381                              <1> comm_int:
  2382                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2383                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2384                              <1> 	; 20/11/2015
  2385                              <1> 	; 18/11/2015
  2386                              <1> 	; 17/11/2015
  2387                              <1> 	; 16/11/2015
  2388                              <1> 	; 09/11/2015
  2389                              <1> 	; 08/11/2015
  2390                              <1> 	; 07/11/2015
  2391                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2392                              <1> 	; 01/11/2015
  2393                              <1> 	; 26/10/2015
  2394                              <1> 	; 23/10/2015
  2395 0000343A 53                  <1> 	push	ebx
  2396 0000343B 56                  <1> 	push	esi
  2397 0000343C 57                  <1> 	push	edi
  2398 0000343D 1E                  <1> 	push 	ds
  2399 0000343E 06                  <1> 	push 	es
  2400                              <1> 	; 18/11/2015
  2401 0000343F 0F20DB              <1> 	mov	ebx, cr3
  2402 00003442 53                  <1> 	push	ebx ; ****
  2403                              <1> 	;
  2404 00003443 51                  <1> 	push	ecx ; ***
  2405 00003444 52                  <1> 	push	edx ; **
  2406                              <1> 	;
  2407 00003445 BB10000000          <1> 	mov	ebx, KDATA
  2408 0000344A 8EDB                <1> 	mov	ds, bx
  2409 0000344C 8EC3                <1> 	mov	es, bx
  2410                              <1> 	;
  2411 0000344E 8B0D[E86A0000]      <1> 	mov	ecx, [k_page_dir]
  2412 00003454 0F22D9              <1> 	mov	cr3, ecx
  2413                              <1> 	; 20/11/2015
  2414                              <1> 	; Interrupt identification register
  2415 00003457 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2416                              <1> 	;
  2417 0000345B 3C08                <1> 	cmp 	al, 8 
  2418 0000345D 7702                <1> 	ja 	short com_i0
  2419                              <1> 	;
  2420                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2421                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2422                              <1> 	; 20/11/2015
  2423                              <1> 	; 17/11/2015
  2424                              <1> 	; 16/11/2015
  2425                              <1> 	; 15/11/2015
  2426                              <1> 	; 24/10/2015
  2427                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2428                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2429                              <1> 	; < serial port 1 interrupt handler >
  2430                              <1> 	;
  2431 0000345F FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2432                              <1> com_i0:
  2433                              <1> 	;push	eax ; *
  2434                              <1> 	; 07/11/2015
  2435 00003461 A2[566B0000]        <1> 	mov 	byte [ccomport], al
  2436                              <1> 	; 09/11/2015
  2437                              <1> 	;movzx	ebx, ax ; 8 or 9
  2438                              <1> 	; 08/01/2022
  2439 00003466 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2440                              <1> 	; 17/11/2015
  2441                              <1>  	; reset request for response status
  2442 00003468 88A3[4C6B0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2443                              <1> 	;
  2444                              <1> 	; 20/11/2015
  2445 0000346E EC                  <1> 	in	al, dx		; read interrupt id. register
  2446 0000346F EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2447 00003471 2404                <1> 	and	al, 4		; received data available?	
  2448 00003473 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2449                              <1> 	;
  2450                              <1> 	; 20/11/2015
  2451 00003475 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2452 00003478 EC                  <1> 	in	al, dx     	; read character
  2453                              <1> 	;JMP	$+2	   	; I/O DELAY
  2454                              <1> 	; 08/11/2015
  2455                              <1> 	; 07/11/2015
  2456 00003479 89DE                <1> 	mov	esi, ebx 
  2457 0000347B 89DF                <1> 	mov	edi, ebx
  2458 0000347D 81C6[506B0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2459 00003483 81C7[526B0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2460 00003489 8806                <1> 	mov	[esi], al ; received char (current char)
  2461                              <1> 	; query
  2462 0000348B 20C0                <1> 	and	al, al
  2463 0000348D 7527                <1> 	jnz	short com_i2
  2464                              <1>    	; response
  2465                              <1> 	; 17/11/2015
  2466                              <1> 	; set request for response status
  2467 0000348F FE83[4C6B0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2468                              <1> 	;
  2469 00003495 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2470 00003499 EC                  <1> 	in	al, dx	   	; read line status register 
  2471 0000349A EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2472 0000349C 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2473 0000349E 7445                <1> 	jz	short com_eoi 	; no
  2474 000034A0 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2475 000034A2 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2476 000034A6 EE                  <1> 	out	dx, al	   	; send on serial port
  2477                              <1> 	; 17/11/2015
  2478 000034A7 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2479 000034AA 7502                <1> 	jne 	short com_i1    ; no
  2480 000034AC 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2481                              <1> com_i1:
  2482                              <1> 	; 17/11/2015
  2483                              <1> 	; reset request for response status (again)
  2484 000034AE FE8B[4C6B0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2485 000034B4 EB2F                <1> 	jmp	short com_eoi
  2486                              <1> com_i2:	
  2487                              <1> 	; 08/11/2015
  2488 000034B6 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2489 000034B8 7417                <1> 	je	short com_i3	; (check for response signal)
  2490                              <1> 	; 07/11/2015
  2491 000034BA 3C04                <1> 	cmp	al, 04h	; EOT
  2492 000034BC 751C                <1> 	jne	short com_i4	
  2493                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2494                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2495                              <1> 	; 08/11/2015
  2496                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2497 000034BE 861D[166B0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2498 000034C4 E80BFFFFFF          <1> 	call 	ctrlbrk
  2499 000034C9 861D[166B0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2500                              <1> 	;mov	al, 04h ; EOT
  2501                              <1> 	; 08/11/2015
  2502 000034CF EB09                <1> 	jmp	short com_i4	
  2503                              <1> com_i3:
  2504                              <1> 	; 08/11/2015
  2505                              <1> 	; If 0FFh has been received just after a query
  2506                              <1> 	; (schar, ZERO), it is a response signal.
  2507                              <1> 	; 17/11/2015
  2508 000034D1 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2509 000034D4 7704                <1> 	ja	short com_i4 ; no
  2510                              <1> 	; reset query status (schar)
  2511 000034D6 8807                <1> 	mov	[edi], al ; 0FFh
  2512 000034D8 FEC0                <1> 	inc	al ; 0
  2513                              <1> com_i4:
  2514                              <1> 	; 27/07/2014
  2515                              <1> 	; 09/07/2014
  2516 000034DA D0E3                <1> 	shl	bl, 1	
  2517 000034DC 81C3[186B0000]      <1> 	add	ebx, ttychr
  2518                              <1> 	; 23/07/2014 (always overwrite)
  2519                              <1> 	;;cmp	word [ebx], 0
  2520                              <1> 	;;ja	short com_eoi
  2521                              <1> 	;
  2522 000034E2 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2523                              <1> 			    ; scan code = 0
  2524                              <1> com_eoi:
  2525                              <1> 	;mov	al, 20h
  2526                              <1> 	;out	20h, al	   ; end of interrupt
  2527                              <1> 	;
  2528                              <1> 	; 07/11/2015
  2529                              <1>       	;pop	eax ; *
  2530 000034E5 A0[566B0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2531                              <1> 	; al = tty number (8 or 9)
  2532 000034EA E8A61A0000          <1>         call	wakeup
  2533                              <1> com_iret:
  2534                              <1> 	; 23/10/2015
  2535 000034EF 5A                  <1> 	pop	edx ; **
  2536 000034F0 59                  <1> 	pop	ecx ; ***
  2537                              <1> 	; 18/11/2015
  2538                              <1> 	;pop	eax ; ****
  2539                              <1> 	;mov	cr3, eax
  2540                              <1> 	;jmp	iiret
  2541 000034F1 E9C5D4FFFF          <1> 	jmp	iiretp
  2542                              <1> 
  2543                              <1> ;hfgchr:
  2544                              <1> ;	db '0123456789ABCDEF?*'
  2545                              <1> ;	db 0
  2546                              <1> 
  2547                              <1> ;iiretp: ; 01/09/2015
  2548                              <1> ;	; 28/08/2015
  2549                              <1> ;	pop	eax ; (*) page directory
  2550                              <1> ;	mov	cr3, eax
  2551                              <1> ;iiret:
  2552                              <1> ;	; 22/08/2014
  2553                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2554                              <1> ;	out	20h, al	; 8259 PORT
  2555                              <1> ;	;
  2556                              <1> ;	pop	es
  2557                              <1> ;	pop	ds
  2558                              <1> ;	pop	edi
  2559                              <1> ;	pop	esi
  2560                              <1> ;	pop	ebx ; 29/08/2014
  2561                              <1> ;	pop 	eax
  2562                              <1> ;	iretd
  2563                              <1> 
  2564                              <1> sp_init:
  2565                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2566                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2567                              <1> 	; 07/11/2015
  2568                              <1> 	; 29/10/2015
  2569                              <1> 	; 26/10/2015
  2570                              <1> 	; 23/10/2015
  2571                              <1> 	; 29/06/2015
  2572                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2573                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2574                              <1> 	; Initialization of Serial Port Communication Parameters
  2575                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2576                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2577                              <1> 	;
  2578                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2579                              <1> 	;
  2580                              <1> 	; INPUT:  (29/06/2015)
  2581                              <1> 	;	AL = 0 for COM1
  2582                              <1> 	;	     1 for COM2
  2583                              <1> 	;	AH = Communication parameters	
  2584                              <1> 	;
  2585                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2586                              <1> 	;	Bit	4	3	2	1	0
  2587                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2588                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2589                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2590                              <1> 	;		11 = even
  2591                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2592                              <1> 	;		Retro UNIX 386 v1 feature only !
  2593                              <1> 	;	Bit	7    6    5  | Baud rate
  2594                              <1> 	;		------------------------
  2595                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2596                              <1> 	;		0    0    1  | 9600 (12)
  2597                              <1> 	;		0    1    0  | 19200 (6) 
  2598                              <1> 	;		0    1	  1  | 38400 (3) 
  2599                              <1> 	;		1    0	  0  | 14400 (8)
  2600                              <1> 	;		1    0	  1  | 28800 (4)
  2601                              <1> 	;		1    1    0  | 57600 (2)
  2602                              <1> 	;		1    1    1  | 115200 (1) 	
  2603                              <1> 	
  2604                              <1> 	; References:	
  2605                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2606                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2607                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2608                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2609                              <1> 	;
  2610                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2611                              <1> 	;
  2612 000034F6 BB[526B0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2613 000034FB 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2614                              <1> 	; 29/10/2015
  2615 000034FF 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2616 00003503 E84F000000          <1> 	call	sp_i3	; call A4	
  2617 00003508 A880                <1> 	test	al, 80h
  2618 0000350A 740E                <1> 	jz	short sp_i0 ; OK..
  2619                              <1> 		; Error !
  2620                              <1> 	;mov	dx, 3F8h
  2621 0000350C 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2622                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2623                              <1> 	; 08/01/2022
  2624 0000350F B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2625 00003511 E841000000          <1> 	call	sp_i3	; call A4	
  2626 00003516 A880                <1> 	test	al, 80h
  2627 00003518 7508                <1> 	jnz	short sp_i1
  2628                              <1> sp_i0:
  2629                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2630                              <1>         ; (INT 14h initialization code disables interrupts.)
  2631                              <1> 	;
  2632 0000351A C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2633 0000351D E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2634                              <1> sp_i1:
  2635 00003522 43                  <1> 	inc	ebx
  2636 00003523 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2637                              <1> 	; 29/10/2015
  2638                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2639                              <1> 	; 08/01/2022
  2640 00003527 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2641 00003529 E829000000          <1> 	call	sp_i3	; call A4	
  2642 0000352E A880                <1> 	test	al, 80h
  2643 00003530 740E                <1> 	jz	short sp_i2 ; OK..
  2644                              <1> 		; Error !
  2645                              <1> 	;mov	dx, 2F8h
  2646 00003532 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2647                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2648                              <1> 	; 08/01/2022
  2649 00003535 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2650 00003537 E81B000000          <1> 	call	sp_i3	; call A4	
  2651 0000353C A880                <1> 	test	al, 80h
  2652 0000353E 7516                <1> 	jnz	short sp_i7
  2653                              <1> sp_i2:
  2654 00003540 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2655                              <1> sp_i6:
  2656                              <1> 	;; COM2 - enabling IRQ 3
  2657                              <1> 	; 08/01/2022
  2658 00003543 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2659                              <1> 	; 07/11/2015
  2660                              <1> 	; 26/10/2015
  2661                              <1> 	;pushf
  2662                              <1> 	;cli
  2663                              <1> 	;;
  2664                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2665                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2666                              <1> 	;in	al, dx 	   		; read register
  2667                              <1> 	;JMP	$+2	   		; I/O DELAY
  2668                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2669                              <1> 	;out	dx, al     		; write back to register
  2670                              <1> 	;JMP	$+2	   		; I/O DELAY
  2671                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2672                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2673                              <1> 	;in	al, dx     		; read register
  2674                              <1> 	;JMP	$+2	   		; I/O DELAY
  2675                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2676                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2677                              <1> 	;out	dx, al 	   		; write back to register
  2678                              <1> 	;JMP	$+2        		; I/O DELAY
  2679                              <1> 	;in	al, 21h    		; read interrupt mask register
  2680                              <1> 	;JMP	$+2	   		; I/O DELAY
  2681                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2682                              <1> 	;out	21h, al    		; write back to register
  2683                              <1> 	;
  2684                              <1> 	; 08/01/2022
  2685 00003545 9C                  <1> 	pushf
  2686 00003546 E8AA000000          <1> 	call	sp_i8
  2687                              <1> 	; 23/10/2015
  2688 0000354B B8[2A340000]        <1> 	mov 	eax, com2_int
  2689 00003550 A3[E9390000]        <1> 	mov	[com2_irq3], eax
  2690                              <1> 	; 26/10/2015
  2691 00003555 9D                  <1> 	popf	
  2692                              <1> sp_i7:
  2693 00003556 C3                  <1> 	retn
  2694                              <1> 
  2695                              <1> sp_i3:
  2696                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2697                              <1> 	; 28/10/2015
  2698 00003557 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2699 00003559 B000                <1> 	mov	al, 0
  2700 0000355B EE                  <1> 	out	dx, al			; disable serial port interrupt
  2701 0000355C EB00                <1> 	JMP	$+2			; I/O DELAY
  2702 0000355E 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2703 00003561 B080                <1> 	mov	al, 80h			
  2704 00003563 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2705                              <1> 	;-----	SET BAUD RATE DIVISOR
  2706                              <1> 	; 26/10/2015
  2707 00003564 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2708                              <1> 					; of the divisor value
  2709 00003567 88C8                <1> 	mov	al, cl	; 1
  2710 00003569 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2711                              <1> 					; 2 = 57600 baud
  2712                              <1> 					; 3 = 38400 baud
  2713                              <1> 					; 6 = 19200 baud
  2714                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2715 0000356A EB00                <1> 	JMP	$+2			; I/O DELAY
  2716 0000356C 28C0                <1> 	sub	al, al
  2717 0000356E FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2718                              <1> 					; of the divisor value
  2719 00003570 EE                  <1> 	out	dx, al ; 0
  2720 00003571 EB00                <1> 	JMP	$+2			; I/O DELAY
  2721                              <1> 	;	
  2722 00003573 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2723                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2724 00003575 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2725 00003578 EE                  <1> 	out	dx, al			
  2726 00003579 EB00                <1> 	JMP	$+2			; I/O DELAY
  2727                              <1> 	; 29/10/2015
  2728 0000357B FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2729 0000357D 30C0                <1> 	xor	al, al			; 0
  2730 0000357F EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2731 00003580 EB00                <1> 	JMP	$+2	
  2732                              <1> sp_i4:
  2733                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2734                              <1> 	; 29/06/2015 (line status after modem status)
  2735 00003582 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2736                              <1> sp_i4s:
  2737 00003585 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2738 00003586 EB00                <1> 	JMP	$+2			; I/O DELAY
  2739 00003588 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2740 0000358A FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2741                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2742 0000358C EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2743                              <1> 	; AL = Line status, AH = Modem status
  2744 0000358D C3                  <1> 	retn
  2745                              <1> 
  2746                              <1> sp_status:
  2747                              <1> 	; 29/06/2015
  2748                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2749                              <1> 	; Get serial port status
  2750 0000358E 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2751 00003592 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2752                              <1> 					; dx = 2FEh for COM2
  2753 00003594 EBEF                <1> 	jmp	short sp_i4s
  2754                              <1> 
  2755                              <1> sp_setp: ; Set serial port communication parameters
  2756                              <1> 	; 04/02/2022 
  2757                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2758                              <1> 	; 08/01/2022
  2759                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2760                              <1> 	; 07/11/2015
  2761                              <1> 	; 29/10/2015
  2762                              <1> 	; 29/06/2015
  2763                              <1> 	; Retro UNIX 386 v1 feature only !	
  2764                              <1> 	;
  2765                              <1> 	; INPUT:
  2766                              <1> 	;	AL = 0 for COM1
  2767                              <1> 	;	     1 for COM2
  2768                              <1> 	;	AH = Communication parameters (*)
  2769                              <1> 	; OUTPUT:
  2770                              <1> 	;	CL = Line status
  2771                              <1> 	;	CH = Modem status
  2772                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2773                              <1> 	;		 'invalid parameter !' 
  2774                              <1> 	;		 	 or
  2775                              <1> 	;		 'device not ready !' error
  2776                              <1> 	;	
  2777                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2778                              <1> 	;	Bit	4	3	2	1	0
  2779                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2780                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2781                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2782                              <1> 	;		11 = even
  2783                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2784                              <1> 	;		Retro UNIX 386 v1 feature only !
  2785                              <1> 	;	Bit	7    6    5  | Baud rate
  2786                              <1> 	;		------------------------
  2787                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2788                              <1> 	;		0    0    1  | 9600 (12)
  2789                              <1> 	;		0    1    0  | 19200 (6) 
  2790                              <1> 	;		0    1	  1  | 38400 (3) 
  2791                              <1> 	;		1    0	  0  | 14400 (8)
  2792                              <1> 	;		1    0	  1  | 28800 (4)
  2793                              <1> 	;		1    1    0  | 57600 (2)
  2794                              <1> 	;		1    1    1  | 115200 (1) 
  2795                              <1> 	;
  2796                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2797                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2798                              <1> 	;
  2799                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2800                              <1> 	;
  2801 00003596 66BAF803            <1> 	mov	dx, 3F8h
  2802 0000359A BB[526B0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2803 0000359F 3C01                <1> 	cmp	al, 1
  2804 000035A1 7770                <1> 	ja 	short sp_invp_err
  2805 000035A3 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2806 000035A5 FECE                <1> 	dec	dh ; 2F8h
  2807 000035A7 43                  <1> 	inc	ebx ; COM2 control byte offset
  2808                              <1> sp_setp1:
  2809                              <1> 	; 29/10/2015
  2810 000035A8 8823                <1> 	mov	[ebx], ah
  2811 000035AA 0FB6CC              <1> 	movzx 	ecx, ah
  2812 000035AD C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2813 000035B0 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2814 000035B3 8A81[22360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2815 000035B9 6689C1              <1> 	mov	cx, ax
  2816 000035BC E896FFFFFF          <1> 	call	sp_i3
  2817 000035C1 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2818 000035C4 A880                <1> 	test	al, 80h
  2819 000035C6 740F                <1> 	jz	short sp_setp2
  2820 000035C8 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2821                              <1> stp_dnr_err:
  2822 000035CB C705[FB6E0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2822 000035D3 0000                <1>
  2823                              <1> 	; CL = Line status, CH = Modem status
  2824 000035D5 F9                  <1> 	stc
  2825 000035D6 C3                  <1> 	retn
  2826                              <1> sp_setp2:
  2827 000035D7 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2828                              <1>         ;jna	sp_i6
  2829                              <1> 		      ; COM1 (3F?h)
  2830                              <1> 	; 24/12/2021
  2831 000035DA 7705                <1> 	ja	short sp_i5
  2832 000035DC E962FFFFFF          <1> 	jmp	sp_i6
  2833                              <1> sp_i5: 
  2834                              <1> 	; 08/01/2022
  2835 000035E1 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2836                              <1> 	; 07/11/2015
  2837                              <1> 	; 26/10/2015
  2838                              <1> 	; 29/06/2015
  2839                              <1> 	;
  2840                              <1> 	;; COM1 - enabling IRQ 4
  2841                              <1> 	;pushf
  2842                              <1> 	;cli
  2843                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2844                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2845                              <1> 	;in	al, dx 	   		; read register
  2846                              <1> 	;JMP	$+2			; I/O DELAY
  2847                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2848                              <1> 	;out	dx, al     		; write back to register
  2849                              <1> 	;JMP	$+2			; I/O DELAY
  2850                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2851                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2852                              <1> 	;in	al, dx     		; read register
  2853                              <1> 	;JMP	$+2			; I/O DELAY
  2854                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2855                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2856                              <1> 	;out	dx, al 	   		; write back to register
  2857                              <1> 	;JMP	$+2        		; I/O DELAY
  2858                              <1> 	;in	al, 21h    		; read interrupt mask register
  2859                              <1> 	;JMP	$+2			; I/O DELAY
  2860                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2861                              <1> 	;out	21h, al    		; write back to register
  2862                              <1> 	;
  2863                              <1> 	; 08/01/2022
  2864 000035E3 9C                  <1> 	pushf
  2865 000035E4 E80C000000          <1> 	call	sp_i8
  2866                              <1> 	; 23/10/2015
  2867 000035E9 B8[33340000]        <1> 	mov 	eax, com1_int
  2868 000035EE A3[E5390000]        <1> 	mov	[com1_irq4], eax
  2869                              <1> 	; 26/10/2015
  2870 000035F3 9D                  <1> 	popf
  2871 000035F4 C3                  <1> 	retn
  2872                              <1> 
  2873                              <1> sp_i8:
  2874                              <1> 	; 08/01/2022
  2875                              <1> 	;pushf
  2876 000035F5 FA                  <1> 	cli
  2877                              <1> 	;
  2878                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2879 000035F6 B2FC                <1> 	mov	dl, 0FCh
  2880 000035F8 EC                  <1> 	in	al, dx 	   		; read register
  2881 000035F9 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2882 000035FB 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2883 000035FD EE                  <1> 	out	dx, al     		; write back to register
  2884 000035FE EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2885                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2886 00003600 B2F9                <1> 	mov	dl, 0F9h
  2887 00003602 EC                  <1> 	in	al, dx     		; read register
  2888 00003603 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2889                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2890 00003605 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2891 00003607 EE                  <1> 	out	dx, al 	   		; write back to register
  2892 00003608 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2893 0000360A E421                <1> 	in	al, 21h    		; read interrupt mask register
  2894 0000360C EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2895                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2896 0000360E 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2897 00003610 E621                <1> 	out	21h, al    		; write back to register
  2898                              <1> 	;
  2899                              <1> 	;popf	
  2900 00003612 C3                  <1> 	retn
  2901                              <1> 
  2902                              <1> sp_invp_err:
  2903 00003613 C705[FB6E0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2903 0000361B 0000                <1>
  2904 0000361D 31C9                <1> 	xor	ecx, ecx
  2905 0000361F 49                  <1> 	dec	ecx ; 0FFFFh
  2906 00003620 F9                  <1> 	stc
  2907 00003621 C3                  <1> 	retn
  2908                              <1> 
  2909                              <1> ; 29/10/2015
  2910                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2911 00003622 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2912                              <1> 
  2913                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2914                              <1> epoch:
  2915                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2916                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2917                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2918                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2919                              <1> 	; 'epoch' procedure prototype: 
  2920                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2921                              <1> 	; 14/11/2012
  2922                              <1> 	; unixboot.asm (boot file configuration)
  2923                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2924                              <1> 	; 21/7/2012
  2925                              <1> 	; 15/7/2012
  2926                              <1> 	; 14/7/2012		
  2927                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2928                              <1> 	; compute current date and time as UNIX Epoch/Time
  2929                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2930                              <1> 	;
  2931                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2932                              <1> 	;
  2933 00003629 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2934 0000362E 86E9                <1>         xchg 	ch,cl
  2935 00003630 66890D[54680000]    <1>         mov 	[hour], cx
  2936 00003637 86F2                <1>         xchg 	dh,dl
  2937 00003639 668915[58680000]    <1>         mov 	[second], dx
  2938                              <1> 	;
  2939 00003640 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2940 00003645 86E9                <1>         xchg 	ch,cl
  2941 00003647 66890D[4E680000]    <1>         mov 	[year], cx
  2942 0000364E 86F2                <1>         xchg 	dh,dl
  2943 00003650 668915[50680000]    <1>         mov 	[month], dx
  2944                              <1> 	;
  2945 00003657 66B93030            <1> 	mov 	cx, 3030h
  2946                              <1> 	;
  2947 0000365B A0[54680000]        <1> 	mov 	al, [hour] ; Hour
  2948                              <1>         	; AL <= BCD number)
  2949 00003660 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2950                              <1> 					; AH = AL / 10h
  2951                              <1> 					; AL = AL MOD 10h
  2952 00003662 D50A                <1>         aad 	; AX= AH*10+AL
  2953 00003664 A2[54680000]        <1> 	mov 	[hour], al
  2954 00003669 A0[55680000]        <1> 	mov 	al, [hour+1] ; Minute
  2955                              <1>         	; AL <= BCD number)
  2956 0000366E D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2957                              <1> 					; AH = AL / 10h
  2958                              <1> 					; AL = AL MOD 10h
  2959 00003670 D50A                <1>         aad 	; AX= AH*10+AL
  2960 00003672 A2[56680000]        <1> 	mov 	[minute], al
  2961 00003677 A0[58680000]        <1> 	mov 	al, [second] ; Second
  2962                              <1>         	; AL <= BCD number)
  2963 0000367C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2964                              <1> 					; AH = AL / 10h
  2965                              <1> 					; AL = AL MOD 10h
  2966 0000367E D50A                <1>         aad 	; AX= AH*10+AL
  2967 00003680 A2[58680000]        <1> 	mov 	[second], al
  2968 00003685 66A1[4E680000]      <1> 	mov 	ax, [year] ; Year (century)
  2969                              <1>  	;push 	ax
  2970                              <1> 	; 08/01/2022
  2971 0000368B 50                  <1> 	push	eax
  2972                              <1> 	   	; AL <= BCD number)
  2973 0000368C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2974                              <1> 					; AH = AL / 10h
  2975                              <1> 					; AL = AL MOD 10h
  2976 0000368E D50A                <1>         aad 	; AX= AH*10+AL
  2977 00003690 B464                <1> 	mov 	ah, 100
  2978 00003692 F6E4                <1> 	mul 	ah
  2979 00003694 66A3[4E680000]      <1> 	mov 	[year], ax
  2980                              <1> 	;pop	ax
  2981                              <1> 	; 08/01/2022
  2982 0000369A 58                  <1> 	pop	eax
  2983 0000369B 88E0                <1> 	mov	al, ah
  2984                              <1>         	; AL <= BCD number)
  2985 0000369D D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2986                              <1> 					; AH = AL / 10h
  2987                              <1> 					; AL = AL MOD 10h
  2988 0000369F D50A                <1>         aad 	; AX= AH*10+AL
  2989 000036A1 660105[4E680000]    <1> 	add 	[year], ax
  2990 000036A8 A0[50680000]        <1> 	mov 	al, [month] ; Month
  2991                              <1>            	; AL <= BCD number)
  2992 000036AD D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2993                              <1> 					; AH = AL / 10h
  2994                              <1> 					; AL = AL MOD 10h
  2995 000036AF D50A                <1>         aad 	; AX= AH*10+AL
  2996 000036B1 A2[50680000]        <1> 	mov 	[month], al	
  2997 000036B6 A0[51680000]        <1>         mov     al, [month+1]      	; Day
  2998                              <1>            	; AL <= BCD number)
  2999 000036BB D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3000                              <1> 					; AH = AL / 10h
  3001                              <1> 					; AL = AL MOD 10h
  3002 000036BD D50A                <1>         aad 	; AX= AH*10+AL
  3003 000036BF A2[52680000]        <1>         mov     [day], al
  3004                              <1> 	
  3005                              <1> convert_to_epoch:
  3006                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3007                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  3008                              <1> 	;
  3009                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3010                              <1> 	;
  3011                              <1> 	; Derived from DALLAS Semiconductor
  3012                              <1> 	; Application Note 31 (DS1602/DS1603)
  3013                              <1> 	; 6 May 1998
  3014 000036C4 29C0                <1> 	sub 	eax, eax
  3015 000036C6 66A1[4E680000]      <1> 	mov 	ax, [year]
  3016 000036CC 662DB207            <1> 	sub 	ax, 1970
  3017 000036D0 BA6D010000          <1> 	mov 	edx, 365
  3018 000036D5 F7E2                <1> 	mul 	edx
  3019 000036D7 31DB                <1> 	xor 	ebx, ebx
  3020 000036D9 8A1D[50680000]      <1> 	mov 	bl, [month]
  3021 000036DF FECB                <1> 	dec 	bl
  3022 000036E1 D0E3                <1> 	shl 	bl, 1
  3023                              <1> 	;sub	edx, edx
  3024 000036E3 668B93[5A680000]    <1> 	mov 	dx, [EBX+DMonth]
  3025 000036EA 8A1D[52680000]      <1>         mov     bl, [day]
  3026 000036F0 FECB                <1> 	dec 	bl
  3027 000036F2 01D0                <1> 	add 	eax, edx
  3028 000036F4 01D8                <1> 	add 	eax, ebx
  3029                              <1> 			; EAX = days since 1/1/1970
  3030 000036F6 668B15[4E680000]    <1> 	mov 	dx, [year]
  3031 000036FD 6681EAB107          <1> 	sub 	dx, 1969
  3032 00003702 66D1EA              <1> 	shr 	dx, 1
  3033 00003705 66D1EA              <1> 	shr 	dx, 1		
  3034                              <1> 		; (year-1969)/4
  3035 00003708 01D0                <1> 	add 	eax, edx
  3036                              <1> 			; + leap days since 1/1/1970
  3037 0000370A 803D[50680000]02    <1> 	cmp 	byte [month], 2	; if past february
  3038 00003711 7610                <1> 	jna 	short cte1
  3039 00003713 668B15[4E680000]    <1> 	mov 	dx, [year]
  3040 0000371A 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3041 0000371E 7503                <1> 	jnz 	short cte1		
  3042                              <1> 			; and if leap year
  3043 00003720 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3044                              <1> cte1: 			; compute seconds since 1/1/1970
  3045 00003723 BA18000000          <1> 	mov 	edx, 24
  3046 00003728 F7E2                <1> 	mul	edx
  3047 0000372A 8A15[54680000]      <1> 	mov 	dl, [hour]
  3048 00003730 01D0                <1> 	add 	eax, edx
  3049                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3050                              <1> 	;mov	ebx, 60
  3051 00003732 B33C                <1> 	mov	bl, 60
  3052 00003734 F7E3                <1> 	mul	ebx
  3053 00003736 8A15[56680000]      <1> 	mov 	dl, [minute]
  3054 0000373C 01D0                <1> 	add 	eax, edx
  3055                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3056                              <1> 	;mov 	ebx, 60
  3057 0000373E F7E3                <1> 	mul	ebx
  3058 00003740 8A15[58680000]      <1> 	mov 	dl, [second]
  3059 00003746 01D0                <1> 	add 	eax, edx
  3060                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3061 00003748 C3                  <1> 	retn
  3062                              <1> 
  3063                              <1> get_rtc_time:
  3064                              <1> 	; 15/03/2015
  3065                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3066                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3067                              <1> 	; INT 1Ah						:
  3068                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3069                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3070                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3071                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3072                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3073                              <1> 	;								
  3074                              <1> RTC_20: 			; GET RTC TIME
  3075 00003749 FA                  <1> 	cli
  3076 0000374A E80AD4FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3077 0000374F 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3078                              <1> 
  3079 00003751 B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3080 00003753 E8E9D3FFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3081 00003758 88C6                <1> 	MOV	DH,AL		; SAVE
  3082 0000375A B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3083 0000375C E8E0D3FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3084 00003761 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3085 00003763 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3086 00003765 B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3087 00003767 E8D5D3FFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3088 0000376C 88C1                <1> 	MOV	CL,AL		; SAVE
  3089 0000376E B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3090 00003770 E8CCD3FFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3091 00003775 88C5                <1> 	MOV	CH,AL		; SAVE
  3092 00003777 F8                  <1> 	CLC			; SET CY= 0
  3093                              <1> RTC_29:
  3094 00003778 FB                  <1> 	sti
  3095 00003779 C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3096                              <1> 
  3097                              <1> get_rtc_date:
  3098                              <1> 	; 15/03/2015
  3099                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3100                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3101                              <1> 	; INT 1Ah						       :
  3102                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3103                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3104                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3105                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3106                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3107                              <1> 	;
  3108                              <1> RTC_40: 			; GET RTC DATE
  3109 0000377A FA                  <1> 	cli
  3110 0000377B E8D9D3FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3111 00003780 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3112                              <1> 
  3113 00003782 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3114 00003784 E8B8D3FFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3115 00003789 88C2                <1> 	MOV	DL,AL		; SAVE
  3116 0000378B B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3117 0000378D E8AFD3FFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3118 00003792 88C6                <1> 	MOV	DH,AL		; SAVE
  3119 00003794 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3120 00003796 E8A6D3FFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3121 0000379B 88C1                <1> 	MOV	CL,AL		; SAVE
  3122 0000379D B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3123 0000379F E89DD3FFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3124 000037A4 88C5                <1> 	MOV	CH,AL		; SAVE
  3125 000037A6 F8                  <1> 	CLC			; SET CY=0
  3126                              <1> RTC_49:
  3127 000037A7 FB                  <1> 	sti
  3128 000037A8 C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3129                              <1> 
  3130                              <1> set_date_time:
  3131                              <1> convert_from_epoch:
  3132                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3133                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3134                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3135                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3136                              <1> 	;
  3137                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3138                              <1> 	;
  3139                              <1> 	; Derived from DALLAS Semiconductor
  3140                              <1> 	; Application Note 31 (DS1602/DS1603)
  3141                              <1> 	; 6 May 1998
  3142                              <1> 	;
  3143                              <1> 	; INPUT:
  3144                              <1> 	; EAX = Unix (Epoch) Time
  3145                              <1> 	;
  3146 000037A9 31D2                <1> 	xor 	edx, edx
  3147 000037AB B93C000000          <1> 	mov 	ecx, 60
  3148 000037B0 F7F1                <1> 	div	ecx
  3149                              <1> 	;mov 	[imin], eax   ; whole minutes
  3150                              <1> 			  ; since 1/1/1970
  3151 000037B2 668915[58680000]    <1> 	mov 	[second], dx  ; leftover seconds
  3152 000037B9 29D2                <1> 	sub 	edx, edx
  3153 000037BB F7F1                <1> 	div	ecx
  3154                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3155                              <1> 	;		      ; since 1/1/1970
  3156 000037BD 668915[56680000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3157 000037C4 31D2                <1> 	xor	edx, edx
  3158                              <1> 	;mov 	cx, 24
  3159 000037C6 B118                <1> 	mov 	cl, 24
  3160 000037C8 F7F1                <1> 	div	ecx
  3161                              <1> 	;mov 	[iday], ax   ; whole days
  3162                              <1> 			     ; since 1/1/1970
  3163 000037CA 668915[54680000]    <1> 	mov 	[hour], dx   ; leftover hours
  3164 000037D1 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3165                              <1> 			     ; 1/1/1968 	
  3166                              <1> 	;mov 	[iday], ax
  3167 000037D6 50                  <1> 	push 	eax
  3168 000037D7 29D2                <1> 	sub	edx, edx
  3169 000037D9 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3170 000037DE F7F1                <1> 	div	ecx
  3171 000037E0 59                  <1> 	pop 	ecx
  3172                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3173 000037E1 6652                <1> 	push 	dx
  3174                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3175 000037E3 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3176 000037E7 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3177 000037E8 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3178                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3179                              <1> 	;mov 	cx, [iday]
  3180 000037EB 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3181 000037EC 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3182 000037EE B96D010000          <1> 	mov 	ecx, 365
  3183 000037F3 31D2                <1> 	xor	edx, edx
  3184                              <1> 	; EAX = iday-lday, EDX = 0
  3185 000037F5 F7F1                <1> 	div	ecx
  3186                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3187                              <1> 	;jday = iday - (iyrs*365) - lday
  3188                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3189                              <1> 	;add	eax, 1968
  3190 000037F7 6605B007            <1> 	add 	ax, 1968     ; compute year
  3191 000037FB 66A3[4E680000]      <1> 	mov 	[year], ax
  3192 00003801 6689D1              <1> 	mov 	cx, dx
  3193                              <1> 	;mov 	dx, [qday]
  3194 00003804 665A                <1> 	pop 	dx
  3195 00003806 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3196 0000380B 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3197 0000380D 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3198 00003811 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3199 00003812 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3200                              <1> cfe1:			
  3201                              <1> 	;mov 	[jday], cx
  3202 00003816 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3203 0000381A 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3204 0000381E 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3205                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3206 00003822 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3207 00003825 731D                <1> 	jnb 	short cfe3
  3208 00003827 664B                <1> 	dec 	bx           ; month = month - 1
  3209 00003829 66D1E3              <1> 	shl 	bx, 1 
  3210 0000382C 668B93[5A680000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3211 00003833 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3212 00003836 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3213 0000383A 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3214 0000383C 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3215 0000383E 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3216 00003840 6642                <1> 	inc 	dx           ; mday = mday + 1
  3217 00003842 EBDE                <1> 	jmp 	short cfe2
  3218                              <1> cfe3:
  3219 00003844 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3220 00003846 66891D[50680000]    <1> 	mov 	[month], bx
  3221 0000384D 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3222 00003850 6641                <1> 	inc 	cx 			  
  3223 00003852 66890D[52680000]    <1> 	mov 	[day], cx
  3224                              <1> 	
  3225                              <1> 	; eax, ebx, ecx, edx is changed at return
  3226                              <1> 	; output ->
  3227                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3228                              <1> 	
  3229                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3230                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3231                              <1> set_date:
  3232 00003859 A0[4F680000]        <1>         mov     al, [year+1]
  3233 0000385E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3234 00003860 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3235                              <1> 			     ; AL = AH * 10h + AL
  3236 00003862 88C5                <1> 	mov 	ch, al ; century (BCD)
  3237 00003864 A0[4E680000]        <1> 	mov 	al, [year]
  3238 00003869 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3239 0000386B D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3240                              <1> 			     ; AL = AH * 10h + AL
  3241 0000386D 88C1                <1> 	mov 	cl, al ; year (BCD)
  3242 0000386F A0[50680000]        <1>         mov 	al, [month]
  3243 00003874 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3244 00003876 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3245                              <1> 			     ; AL = AH * 10h + AL
  3246 00003878 88C6                <1> 	mov 	dh, al ; month (BCD)
  3247 0000387A A0[52680000]        <1> 	mov 	al, [day]
  3248 0000387F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3249 00003881 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3250                              <1> 			     ; AL = AH * 10h + AL
  3251 00003883 88C6                <1> 	mov 	dh, al ; day (BCD)
  3252                              <1> 	; Set real-time clock date
  3253 00003885 E879000000          <1> 	call	set_rtc_date
  3254                              <1> set_time:
  3255                              <1>         ; Read real-time clock time 
  3256                              <1> 	; (get day light saving time bit status)
  3257 0000388A FA                  <1>  	cli
  3258 0000388B E8C9D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3259                              <1> 	; cf = 1 -> al = 0
  3260 00003890 7207                <1>         jc      short stime1
  3261 00003892 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3262 00003894 E8A8D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3263                              <1> stime1:
  3264 00003899 FB                  <1> 	sti
  3265 0000389A 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3266 0000389C 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3267                              <1> 	; DL = 1 or 0 (day light saving time)
  3268                              <1> 	;	
  3269 0000389E A0[54680000]        <1> 	mov 	al, [hour]
  3270 000038A3 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3271 000038A5 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3272                              <1> 			     ; AL = AH * 10h + AL
  3273 000038A7 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3274 000038A9 A0[56680000]        <1>         mov     al, [minute]
  3275 000038AE D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3276 000038B0 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3277                              <1> 			     ; AL = AH * 10h + AL
  3278 000038B2 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3279 000038B4 A0[58680000]        <1>         mov     al, [second]
  3280 000038B9 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3281 000038BB D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3282                              <1> 			     ; AL = AH * 10h + AL
  3283 000038BD 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3284                              <1> 	; Set real-time clock time
  3285                              <1>  	; call	set_rtc_time
  3286                              <1> set_rtc_time:
  3287                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3288                              <1> 	; 15/03/2015							  :
  3289                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3290                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3291                              <1> 	; INT 1Ah							  :
  3292                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3293                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3294                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3295                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3296                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3297                              <1> 	;								  :
  3298                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3299                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3300                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3301                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3302                              <1> 	;								  :
  3303                              <1> RTC_30: 			; SET RTC TIME
  3304 000038BF FA                  <1> 	cli
  3305 000038C0 E894D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3306 000038C5 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3307 000038C7 E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3308                              <1> RTC_35:
  3309 000038CC 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3310 000038CE B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3311 000038D0 E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3312 000038D5 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3313 000038D7 B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3314 000038D9 E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3315 000038DE 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3316 000038E0 B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3317 000038E2 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3318                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3319 000038E7 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3320 000038EB E851D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3321 000038F0 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3322 000038F2 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3323 000038F4 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3324 000038F7 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3325 000038F9 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3326 000038FB E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3327 00003900 F8                  <1> 	CLC			; SET CY= 0
  3328 00003901 FB                  <1> 	sti
  3329 00003902 C3                  <1> 	RETn			; RETURN WITH CY= 0
  3330                              <1> 
  3331                              <1> set_rtc_date:
  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) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3338                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3339                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3340                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3341                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3342                              <1> 	;							   :
  3343                              <1> RTC_50: 			; SET RTC DATE
  3344 00003903 FA                  <1> 	cli
  3345 00003904 E850D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3346 00003909 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3347 0000390B E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3348                              <1> RTC_55:
  3349 00003910 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3350 00003914 E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3351 00003919 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3352 0000391B B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3353 0000391D E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3354 00003922 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3355 00003924 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3356 00003926 E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3357 0000392B 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3358 0000392D B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3359 0000392F E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3360 00003934 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3361 00003936 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3362 00003938 E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3363                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3364 0000393D 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3365 00003941 E8FBD1FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3366 00003946 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3367 00003948 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3368 0000394A E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3369 0000394F F8                  <1> 	CLC			; SET CY= 0
  3370 00003950 FB                  <1> 	sti
  3371 00003951 C3                  <1> 	RETn			; RETURN CY=0
  3372                              <1> 
  3373                              <1> 	; 15/03/2015
  3374                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3375 00003952 B426                <1> 	mov	ah, 26h
  3376 00003954 B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3377 00003956 E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3378 0000395B B482                <1> 	mov	ah, 82h
  3379 0000395D B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3380 0000395F E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3381 00003964 B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3382 00003966 E8D6D1FFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3383 0000396B B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3384                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3385                              <1> 	;RETn
  3386                              <1> 	; 12/02/2022
  3387 0000396D E9CFD1FFFF          <1> 	jmp	CMOS_READ
  3388                              <1> 
  3389                              <1> 	; 15/03/2015
  3390                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3391                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3392 00003972 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3393                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3394 00003973 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3395 00003975 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3396 00003976 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3397 00003978 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3398 00003979 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3399 0000397B 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3400 0000397D E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3401 0000397F B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3402 00003981 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3403 00003983 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3404 00003985 90                  <1> 	nop			; I/O DELAY
  3405 00003986 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3406                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3407 00003988 9D                  <1> 	popf	
  3408 00003989 C3                  <1> 	RETn
  3409                              <1> 
  3410                              <1> bf_init:
  3411                              <1> 	; 14/08/2015
  3412                              <1> 	; 02/07/2015
  3413                              <1> 	; 01/07/2015
  3414                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3415                              <1> 	; Buffer (pointer) initialization !
  3416                              <1> 	; 
  3417                              <1> 	; 17/07/2013 - 24/07/2013
  3418                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3419                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3420                              <1> 	;
  3421 0000398A BF[6C6E0000]        <1> 	mov	edi, bufp 
  3422 0000398F B8[5C7B0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3423 00003994 29D2                <1> 	sub	edx, edx
  3424 00003996 FECA                <1> 	dec	dl
  3425 00003998 31C9                <1> 	xor	ecx, ecx
  3426 0000399A 49                  <1> 	dec	ecx
  3427                              <1> bi0:
  3428 0000399B 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3429 000039A0 AB                  <1> 	stosd
  3430 000039A1 89C6                <1> 	mov	esi, eax
  3431 000039A3 8916                <1> 	mov	[esi], edx ; 000000FFh
  3432                              <1> 			    ; Not a valid device sign
  3433 000039A5 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3434                              <1> 		      ; Not a valid block number sign 	 	
  3435 000039A8 3D[2C6F0000]        <1> 	cmp	eax, buffer
  3436 000039AD 77EC                <1> 	ja	short bi0
  3437 000039AF B8[5C7B0000]        <1> 	mov	eax, sb0
  3438 000039B4 AB                  <1> 	stosd
  3439 000039B5 B8[647D0000]        <1> 	mov	eax, sb1
  3440 000039BA AB                  <1> 	stosd
  3441 000039BB 89C6                <1> 	mov	esi, eax ; offset sb1
  3442 000039BD 8916                <1> 	mov	[esi], edx ; 000000FFh
  3443                              <1> 			    ; Not a valid device sign
  3444 000039BF 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3445                              <1> 		      ; Not a valid block number sign 	 
  3446                              <1> 	; 14/08/2015
  3447                              <1> 	;call 	rdev_init
  3448                              <1> 	;retn
  3449                              <1> 
  3450                              <1> rdev_init: ; root device, super block buffer initialization
  3451                              <1> 	; 01/02/2022
  3452                              <1> 	; 14/08/2015
  3453                              <1> 	; Retro UNIX 386 v1 feature only !
  3454                              <1> 	;
  3455                              <1> 	; NOTE: Disk partitions (file systems), logical
  3456                              <1> 	; drive initialization, partition's start sector etc.
  3457                              <1> 	; will be coded here, later in 'ldrv_init'	
  3458                              <1> 
  3459 000039C2 0FB605[DA650000]    <1> 	movzx	eax, byte [boot_drv]
  3460                              <1> rdi_0:
  3461 000039C9 3C80                <1> 	cmp	al, 80h
  3462 000039CB 7202                <1> 	jb	short rdi_1
  3463 000039CD 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3464                              <1> rdi_1:
  3465 000039CF A2[926E0000]        <1> 	mov	[rdev], al
  3466 000039D4 BB[5C7B0000]        <1>         mov	ebx, sb0 ; super block buffer
  3467 000039D9 8903                <1> 	mov 	[ebx], eax
  3468 000039DB B001                <1> 	mov	al, 1 ; eax = 1
  3469 000039DD 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3470                              <1> 	;call 	diskio
  3471                              <1> 	;retn
  3472                              <1> 	; 01/02/2022
  3473 000039E0 E972240000          <1> 	jmp	diskio
  3474                              <1> 
  3475                              <1> ; 23/10/2015
  3476                              <1> com1_irq4:
  3477 000039E5 [ED390000]          <1> 	dd dummy_retn
  3478                              <1> com2_irq3:
  3479 000039E9 [ED390000]          <1> 	dd dummy_retn
  3480                              <1> 
  3481                              <1> dummy_retn:
  3482 000039ED C3                  <1> 	retn
  2046                                  %include 'u1.s'        ; 10/05/2015
  2047                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2048                              <1> ; Last Modification: 27/02/2022
  2049                              <1> ; ----------------------------------------------------------------------------
  2050                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2051                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2052                              <1> ;
  2053                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2054                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2055                              <1> ; <Bell Laboratories (17/3/1972)>
  2056                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2057                              <1> ;
  2058                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2059                              <1> ;
  2060                              <1> ; ****************************************************************************
  2061                              <1> ; 23/11/2015
  2062                              <1> 
  2063                              <1> unkni: ; / used for all system calls
  2064                              <1> sysent: ; < enter to system call >
  2065                              <1> 	; 27/02/2022
  2066                              <1> 	; 01/02/2022
  2067                              <1> 	; 19/10/2015
  2068                              <1> 	; 21/09/2015
  2069                              <1> 	; 01/07/2015
  2070                              <1> 	; 19/05/2015
  2071                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2072                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2073                              <1> 	;
  2074                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2075                              <1> 	; The trap type is determined and an indirect jump is made to 
  2076                              <1> 	; the appropriate system call handler. If there is a trap inside
  2077                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2078                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2079                              <1> 	; instructor is decoded to get the the system code part (see
  2080                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2081                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2082                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2083                              <1> 	; is called. If the call is legitimate control passes to the
  2084                              <1> 	; appropriate system routine.
  2085                              <1> 	;
  2086                              <1> 	; Calling sequence:
  2087                              <1> 	;	Through a trap caused by any sys call outside the system.
  2088                              <1> 	; Arguments:
  2089                              <1> 	;	Arguments of particular system call.	
  2090                              <1> 	; ...............................................................
  2091                              <1> 	;	
  2092                              <1> 	; Retro UNIX 8086 v1 modification: 
  2093                              <1> 	;       System call number is in EAX register.
  2094                              <1> 	;
  2095                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2096                              <1> 	;	registers depending of function details.
  2097                              <1>   	;
  2098                              <1> 	; 16/04/2015
  2099 000039EE 368925[A46E0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2100                              <1> 	; save user registers
  2101 000039F5 1E                  <1> 	push	ds
  2102 000039F6 06                  <1> 	push	es
  2103 000039F7 0FA0                <1> 	push	fs
  2104 000039F9 0FA8                <1> 	push	gs
  2105 000039FB 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2106                              <1> 	;
  2107                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2108                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2109                              <1> 	;	for saving/restoring user registers.)
  2110                              <1> 	;
  2111 000039FC 50                  <1> 	push	eax ; 01/07/2015
  2112 000039FD 66B81000            <1> 	mov     ax, KDATA
  2113 00003A01 8ED8                <1>         mov     ds, ax
  2114 00003A03 8EC0                <1>         mov     es, ax
  2115 00003A05 8EE0                <1>         mov     fs, ax
  2116 00003A07 8EE8                <1>         mov     gs, ax
  2117 00003A09 A1[E86A0000]        <1> 	mov	eax, [k_page_dir]
  2118 00003A0E 0F22D8              <1> 	mov	cr3, eax
  2119 00003A11 58                  <1> 	pop	eax ; 01/07/2015
  2120                              <1> 	; 19/10/2015
  2121 00003A12 FC                  <1> 	cld
  2122                              <1> 	;
  2123 00003A13 FE05[A16E0000]      <1> 	inc	byte [sysflg]
  2124                              <1> 		; incb sysflg / indicate a system routine is in progress
  2125 00003A19 FB                  <1>         sti 	; 18/01/2014
  2126                              <1> 	;jnz	panic ; 24/05/2013
  2127                              <1> 		; beq 1f
  2128                              <1> 		; jmp panic ; / called if trap inside system
  2129                              <1> 	; 01/02/2022
  2130 00003A1A 7405                <1> 	jz	short sysent_1
  2131 00003A1C E979F9FFFF          <1> 	jmp	panic
  2132                              <1> sysent_1:
  2133                              <1> ;1:	; 16/04/2015
  2134 00003A21 A3[AC6E0000]        <1> 	mov	[u.r0], eax
  2135 00003A26 8925[A86E0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2136                              <1> 	;
  2137                              <1> 		; mov $s.syst+2,clockp
  2138                              <1> 		; mov r0,-(sp) / save user registers 
  2139                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2140                              <1> 			   ; / in u.r0
  2141                              <1> 		; mov r1,-(sp)
  2142                              <1> 		; mov r2,-(sp)
  2143                              <1> 		; mov r3,-(sp)
  2144                              <1> 		; mov r4,-(sp)
  2145                              <1> 		; mov r5,-(sp)
  2146                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2147                              <1> 		             ; / arithmetic unit
  2148                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2149                              <1> 		             ; / extended arithmetic unit
  2150                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2151                              <1> 		             ; / arithmetic unit
  2152                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2153                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2154                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2155                              <1> 		; sub $sys,r0 / get xxx code
  2156 00003A2C C1E002              <1> 	shl	eax, 2
  2157                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2158 00003A2F 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2159                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2160                              <1> 	;jnb	short badsys
  2161                              <1> 		; bhis badsys / yes, bad system call
  2162                              <1> 	; 27/02/2022
  2163 00003A34 7205                <1> 	jb	short _2
  2164 00003A36 E954010000          <1> 	jmp	badsys
  2165                              <1> _2:
  2166                              <1> 	; 27/02/2022
  2167                              <1> 	;cmc
  2168                              <1> 	;pushf	
  2169                              <1> 	;push	eax
  2170 00003A3B 8B2D[A46E0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2171                              <1> 	;mov	al, 0FEh ; 11111110b
  2172                              <1> 	;;adc	al, 0 ; al = al + cf
  2173                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2174 00003A41 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2175                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2176                              <1> 				 ; / and clear carry bit
  2177                              <1> 	;pop	ebp ; eax
  2178 00003A45 89C5                <1> 	mov	ebp, eax
  2179                              <1> 	;popf
  2180                              <1>         ;;jc	badsys
  2181                              <1> 	; 27/02/2022
  2182                              <1> 	;jnc	short _3
  2183                              <1> 	;jmp	badsys
  2184                              <1> ;_3:
  2185 00003A47 A1[AC6E0000]        <1> 	mov	eax, [u.r0]
  2186                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2187 00003A4C FFA5[523A0000]      <1> 	jmp	dword [ebp+syscalls]
  2188                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2189                              <1> 		            ; / to proper system routine.
  2190                              <1> syscalls: ; 1:
  2191                              <1> 	; 21/09/2015
  2192                              <1> 	; 01/07/2015
  2193                              <1> 	; 16/04/2015 (32 bit address modification) 
  2194 00003A52 [593B0000]          <1> 	dd sysrele	; / 0
  2195 00003A56 [013C0000]          <1> 	dd sysexit 	; / 1
  2196 00003A5A [2C3D0000]          <1> 	dd sysfork 	; / 2
  2197 00003A5E [323E0000]          <1> 	dd sysread 	; / 3
  2198 00003A62 [453E0000]          <1> 	dd syswrite 	; / 4
  2199 00003A66 [AE3E0000]          <1> 	dd sysopen 	; / 5
  2200 00003A6A [DD3F0000]          <1> 	dd sysclose 	; / 6
  2201 00003A6E [A73C0000]          <1> 	dd syswait 	; / 7
  2202 00003A72 [5A3F0000]          <1> 	dd syscreat 	; / 8
  2203 00003A76 [8F430000]          <1> 	dd syslink 	; / 9
  2204 00003A7A [4B440000]          <1> 	dd sysunlink 	; / 10
  2205 00003A7E [12450000]          <1> 	dd sysexec 	; / 11
  2206 00003A82 [464B0000]          <1> 	dd syschdir 	; / 12
  2207 00003A86 [284C0000]          <1> 	dd systime 	; / 13
  2208 00003A8A [963F0000]          <1> 	dd sysmkdir 	; / 14
  2209 00003A8E [984B0000]          <1> 	dd syschmod 	; / 15
  2210 00003A92 [F84B0000]          <1> 	dd syschown 	; / 16
  2211 00003A96 [5B4C0000]          <1> 	dd sysbreak 	; / 17
  2212 00003A9A [D0480000]          <1> 	dd sysstat 	; / 18
  2213 00003A9E [2B4D0000]          <1> 	dd sysseek 	; / 19
  2214 00003AA2 [3D4D0000]          <1> 	dd systell 	; / 20
  2215 00003AA6 [FA570000]          <1> 	dd sysmount 	; / 21
  2216 00003AAA [D9580000]          <1> 	dd sysumount 	; / 22
  2217 00003AAE [B94D0000]          <1> 	dd syssetuid 	; / 23
  2218 00003AB2 [EA4D0000]          <1> 	dd sysgetuid 	; / 24
  2219 00003AB6 [374C0000]          <1> 	dd sysstime 	; / 25
  2220 00003ABA [AD4D0000]          <1> 	dd sysquit 	; / 26
  2221 00003ABE [A14D0000]          <1> 	dd sysintr 	; / 27
  2222 00003AC2 [AD480000]          <1> 	dd sysfstat 	; / 28
  2223 00003AC6 [F53F0000]          <1> 	dd sysemt 	; / 29
  2224 00003ACA [3D400000]          <1> 	dd sysmdate 	; / 30
  2225 00003ACE [97400000]          <1> 	dd sysstty 	; / 31
  2226 00003AD2 [82420000]          <1> 	dd sysgtty 	; / 32
  2227 00003AD6 [38400000]          <1> 	dd sysilgins 	; / 33
  2228 00003ADA [10610000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2229                              <1> 			     ; 11/06/2014
  2230 00003ADE [27610000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2231                              <1> 			     ; 01/07/2015
  2232 00003AE2 [FF610000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2233                              <1> 			     ; 21/09/2015 - get last error number
  2234                              <1> end_of_syscalls:
  2235                              <1> 
  2236                              <1> error:
  2237                              <1> 	; 17/09/2015
  2238                              <1> 	; 03/09/2015
  2239                              <1> 	; 01/09/2015
  2240                              <1> 	; 09/06/2015
  2241                              <1> 	; 13/05/2015
  2242                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2243                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2244                              <1> 	;
  2245                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2246                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2247                              <1> 	;
  2248                              <1> 	; INPUTS -> none
  2249                              <1> 	; OUTPUTS ->
  2250                              <1> 	;	processor status - carry (c) bit is set (means error)
  2251                              <1> 	;
  2252                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2253                              <1> 	; 	      Because, jumps to error procedure
  2254                              <1> 	;	      disrupts push-pop nesting balance)
  2255                              <1> 	;
  2256 00003AE6 8B2D[A46E0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2257 00003AEC 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2258                              <1> 				 ; (system call will return with cf = 1)
  2259                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2260                              <1> 		               ; / users stack
  2261                              <1> 	; 17/09/2015
  2262 00003AF0 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2263                              <1> 				 ; for saving/restoring user registers	
  2264                              <1> 	;cmp	ebp, [u.usp]
  2265                              <1> 	;je	short err0	
  2266 00003AF3 892D[A86E0000]      <1> 	mov	[u.usp], ebp
  2267                              <1> ;err0:
  2268                              <1> 	; 01/09/2015
  2269 00003AF9 8B25[A86E0000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2270                              <1> 				    ; 10/04/2013
  2271                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2272                              <1> 				    ; related procedures will jump to 'error'
  2273                              <1> 				    ; procedure directly without returning to 
  2274                              <1> 				    ; the caller procedure. So, stack pointer
  2275                              <1>                                     ; must be restored here.)
  2276                              <1> 	; 13/05/2015
  2277                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2278                              <1> 	;	'get last error' system call later. 	
  2279                              <1> 
  2280                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2281 00003AFF C605[0D6F0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2282                              <1> 
  2283                              <1> sysret: ; < return from system call>
  2284                              <1> 	; 01/02/2022
  2285                              <1> 	; 10/09/2015
  2286                              <1> 	; 29/07/2015
  2287                              <1> 	; 25/06/2015
  2288                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2289                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2290                              <1> 	;
  2291                              <1> 	; 'sysret' first checks to see if process is about to be 
  2292                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2293                              <1> 	; If not, following happens:	 
  2294                              <1> 	; 	1) The user's stack pointer is restored.
  2295                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2296                              <1> 	;	   i-node has been modified. If it has, it is written out
  2297                              <1> 	;	   via 'ppoke'.
  2298                              <1> 	;	3) If the super block has been modified, it is written out
  2299                              <1> 	;	   via 'ppoke'.				
  2300                              <1> 	;	4) If the dismountable file system's super block has been
  2301                              <1> 	;	   modified, it is written out to the specified device
  2302                              <1> 	;	   via 'ppoke'.
  2303                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2304                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2305                              <1> 	;	   another user a chance to run.
  2306                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2307                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2308                              <1> 	;
  2309                              <1> 	; Calling sequence:
  2310                              <1> 	;	jump table or 'br sysret'
  2311                              <1> 	; Arguments: 
  2312                              <1> 	;	-	
  2313                              <1> 	; ...............................................................
  2314                              <1> 	;	
  2315                              <1> 	; ((AX=r1 for 'iget' input))
  2316                              <1> 	;	
  2317                              <1> 	;xor	ax, ax ; 04/05/2013
  2318                              <1> 	; 01/02/2022
  2319 00003B06 31C0                <1> 	xor	eax, eax
  2320                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2321 00003B08 FEC0                <1> 	inc	al ; 04/05/2013
  2322 00003B0A 3805[F46E0000]      <1> 	cmp	[u.bsys], al ; 1
  2323                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2324                              <1>         ;jnb	sysexit ; 04/05/2013
  2325                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2326                              <1> 	; 01/02/2022
  2327 00003B10 7205                <1> 	jb	short sysret_2
  2328 00003B12 E9EA000000          <1> 	jmp	sysexit
  2329                              <1> sysret_2:
  2330                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2331                              <1> 		; mov u.sp,sp / no point stack to users stack
  2332 00003B17 FEC8                <1> 	dec 	al ; mov ax, 0
  2333                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2334 00003B19 E884160000          <1> 	call	iget
  2335                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2336                              <1> 		            ; / it is written out
  2337 00003B1E 6631C0              <1> 	xor 	ax, ax ; 0
  2338 00003B21 3805[9F6E0000]      <1> 	cmp	[smod], al ; 0
  2339                              <1> 		; tstb	smod / has the super block been modified
  2340 00003B27 7614                <1> 	jna	short sysret1
  2341                              <1> 		; beq	1f / no, 1f
  2342 00003B29 A2[9F6E0000]        <1> 	mov	[smod], al ; 0
  2343                              <1> 		; clrb smod / yes, clear smod
  2344 00003B2E BB[5C7B0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2345 00003B33 66810B0002          <1>    	or	word [ebx], 200h ;;
  2346                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2347                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2348                              <1> 		      	      ; / output
  2349                              <1> 	; AX = 0
  2350 00003B38 E802220000          <1> 	call 	poke ; 07/08/2013
  2351                              <1> 	;call	ppoke
  2352                              <1> 	; AX = 0
  2353                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2354                              <1> sysret1: ;1:
  2355 00003B3D 3805[A06E0000]      <1> 	cmp	[mmod], al ; 0
  2356                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2357                              <1> 		           ; / system
  2358 00003B43 7614                <1> 	jna	short sysrel0
  2359                              <1> 		; beq 1f / been modified?  no, 1f
  2360 00003B45 A2[A06E0000]        <1> 	mov	[mmod], al ; 0	
  2361                              <1> 		; clrb	mmod / yes, clear mmod
  2362                              <1>         ;mov    ax, [mntd]
  2363                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2364 00003B4A BB[647D0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2365                              <1>         ;;mov	[ebx], al
  2366                              <1> 	;mov    [sb1], al
  2367                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2368 00003B4F 66810B0002          <1> 	or	word [ebx], 200h
  2369                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2370                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2371 00003B54 E8E6210000          <1> 	call	poke ; 07/08/2013
  2372                              <1> 	;call	ppoke 
  2373                              <1> 		; jsr r0,ppoke / write it out to its device
  2374                              <1>         ;xor    al, al ; 26/04/2013       
  2375                              <1> ;1:
  2376                              <1> 		; tstb uquant / is the time quantum 0?
  2377                              <1> 		; bne 1f / no, don't swap it out
  2378                              <1> 
  2379                              <1> sysrele: ; < release >
  2380                              <1> 	; 14/10/2015
  2381                              <1> 	; 01/09/2015
  2382                              <1> 	; 24/07/2015
  2383                              <1> 	; 14/05/2015
  2384                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2385                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2386                              <1> 	;
  2387                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2388                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2389                              <1> 	; turns off the system flag. It then checked to see if there is
  2390                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2391                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2392                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2393                              <1> 	; the user, a rti is made.
  2394                              <1> 	;
  2395                              <1> 	; Calling sequence:
  2396                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2397                              <1> 	; Arguments:
  2398                              <1> 	;	-	
  2399                              <1> 	; ...............................................................
  2400                              <1> 	;	
  2401                              <1> 	; 23/02/2014 (swapret)
  2402                              <1> 	; 22/09/2013
  2403                              <1> sysrel0: ;1:
  2404 00003B59 803D[E86E0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2405                              <1> 		; tstb uquant / is the time quantum 0?
  2406 00003B60 7705                <1>         ja      short swapret
  2407                              <1> 		; bne 1f / no, don't swap it out
  2408                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2409 00003B62 E8D3120000          <1> 	call	tswap
  2410                              <1> 		; jsr r0,tswap / yes, swap it out
  2411                              <1> ;
  2412                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2413                              <1> swapret: ;1:
  2414                              <1> 	; 10/09/2015
  2415                              <1> 	; 01/09/2015
  2416                              <1> 	; 14/05/2015
  2417                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2418                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2419                              <1> 	; cli
  2420                              <1> 	; 24/07/2015
  2421                              <1> 	;
  2422                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2423                              <1> 	;; mov	esp, [u.usp]
  2424                              <1> 
  2425                              <1> 	; 22/09/2013
  2426 00003B67 E8A5140000          <1> 	call	isintr
  2427                              <1> 	; 20/10/2013
  2428 00003B6C 7405                <1> 	jz	short sysrel1
  2429 00003B6E E877000000          <1> 	call	intract
  2430                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2431                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2432                              <1> 		               ; / action
  2433                              <1> sysrel1:
  2434 00003B73 FA                  <1> 	cli ; 14/10/2015
  2435 00003B74 FE0D[A16E0000]      <1> 	dec	byte [sysflg]
  2436                              <1> 		; decb sysflg / turn system flag off
  2437 00003B7A A1[FF6E0000]        <1> 	mov     eax, [u.pgdir]
  2438 00003B7F 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2439                              <1> 			  ; (others are different than kernel page tables) 
  2440                              <1> 	; 10/09/2015
  2441 00003B82 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2442                              <1> 		; mov (sp)+,sc / restore user registers
  2443                              <1> 		; mov (sp)+,mq
  2444                              <1> 		; mov (sp)+,ac
  2445                              <1> 		; mov (sp)+,r5
  2446                              <1> 		; mov (sp)+,r4
  2447                              <1> 		; mov (sp)+,r3
  2448                              <1> 		; mov (sp)+,r2
  2449                              <1> 	;
  2450 00003B83 A1[AC6E0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2451 00003B88 0FA9                <1> 	pop	gs
  2452 00003B8A 0FA1                <1> 	pop	fs
  2453 00003B8C 07                  <1> 	pop	es
  2454 00003B8D 1F                  <1> 	pop	ds
  2455 00003B8E CF                  <1> 	iretd	
  2456                              <1> 		; rti / no, return from interrupt
  2457                              <1> 
  2458                              <1> badsys:
  2459                              <1> 	; 27/02/2022
  2460                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2461                              <1> 	; (Major Modification: 'core' dumping procedure in
  2462                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2463                              <1> 	;	has been changed to print 'Invalid System Call !'
  2464                              <1> 	;	message on the user's console tty.)
  2465                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2466                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2467                              <1> 	; (EAX = Function number)  
  2468                              <1> 	;
  2469 00003B8F FE05[F46E0000]      <1> 	inc	byte [u.bsys]
  2470                              <1> 	;
  2471 00003B95 8B1D[A46E0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2472 00003B9B 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2473 00003B9D E86FDBFFFF          <1> 	call	dwordtohex
  2474 00003BA2 8915[42680000]      <1> 	mov	[bsys_msg_eip], edx
  2475 00003BA8 A3[46680000]        <1> 	mov	[bsys_msg_eip+4], eax
  2476 00003BAD A1[AC6E0000]        <1> 	mov	eax, [u.r0]
  2477 00003BB2 E85ADBFFFF          <1> 	call	dwordtohex
  2478 00003BB7 8915[32680000]      <1> 	mov	[bsys_msg_eax], edx
  2479 00003BBD A3[36680000]        <1> 	mov	[bsys_msg_eax+4], eax
  2480                              <1> 	; 27/02/2022
  2481                              <1> 	;xor	eax, eax
  2482                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2483                              <1> 	;mov	ebx, [u.fofp]
  2484                              <1> 	;mov	[ebx], eax
  2485                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2486                              <1> 	;inc	eax
  2487                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2488                              <1> 		; writei
  2489                              <1> 		; INPUTS ->
  2490                              <1> 		;    r1 - inode number
  2491                              <1> 		;    u.count - byte count to be written
  2492                              <1> 		;    u.base - points to user buffer
  2493                              <1> 		;    u.fofp - points to word with current file offset
  2494                              <1> 		; OUTPUTS ->
  2495                              <1> 		;    u.count - cleared
  2496                              <1> 		;    u.nread - accumulates total bytes passed back	
  2497                              <1> 		;
  2498                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2499                              <1> 	;call	writei
  2500                              <1> 	;;mov	eax, 1
  2501                              <1> 	;jmp	sysexit
  2502                              <1> 
  2503                              <1> 	; 27/02/2022
  2504 00003BC2 BE[13680000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2505 00003BC7 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2506 00003BCE 8A83[076C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2507 00003BD4 C605[176B0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2508 00003BDB A2[FA6E0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2509 00003BE0 E8FF250000          <1> 	call	print_cmsg
  2510                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2511 00003BE5 E9FCFEFFFF          <1> 	jmp	error
  2512                              <1> 
  2513                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2514                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2515                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2516                              <1> 		; br 1f / error
  2517                              <1> 		; neg r1 / negate the i-number to open the core image file
  2518                              <1> 		       ; / for writing
  2519                              <1> 		; jsr r0,iopen / open the core image file
  2520                              <1> 		; jsr r0,itrunc / free all associated blocks
  2521                              <1> 		; br 2f
  2522                              <1> ;1:
  2523                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2524                              <1> 		; jsr r0,maknod / make an i-node
  2525                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2526                              <1> ;2:
  2527                              <1> 		; mov $core,u.base / move address core to u.base
  2528                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2529                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2530                              <1> 		; clr u.off / clear user offset
  2531                              <1> 		; jsr r0,writei / write out the core image to the user
  2532                              <1> 		; mov $user,u.base / pt. u.base to user
  2533                              <1> 		; mov $64.,u.count / u.count = 64
  2534                              <1> 		; jsr r0,writei / write out all the user parameters
  2535                              <1> 		; neg r1 / make i-number positive
  2536                              <1> 		; jsr r0,iclose / close the core image file
  2537                              <1> 		; br sysexit /
  2538                              <1> ;3:
  2539                              <1> 		; <core\0\0>
  2540                              <1> 
  2541                              <1> intract: ; / interrupt action
  2542                              <1> 	; 14/10/2015
  2543                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2544                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2545                              <1> 	;
  2546                              <1> 	; Retro UNIX 8086 v1 modification !
  2547                              <1> 	; (Process/task switching and quit routine by using
  2548                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2549                              <1> 	;
  2550                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2551                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2552                              <1> 	;		'intract' will jump to 'sysexit'.
  2553                              <1> 	;	    Intract will return to the caller 
  2554                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2555                              <1> 	; 14/10/2015
  2556 00003BEA FB                  <1> 	sti
  2557                              <1> 	; 07/12/2013	
  2558 00003BEB 66FF05[EC6E0000]    <1> 	inc 	word [u.quit]
  2559 00003BF2 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2560 00003BF4 66FF0D[EC6E0000]    <1> 	dec	word [u.quit]
  2561                              <1> 	; 16/04/2015
  2562 00003BFB C3                  <1> 	retn
  2563                              <1> intrct0:	
  2564 00003BFC 58                  <1> 	pop	eax ; call intract -> retn
  2565                              <1> 	;
  2566 00003BFD 31C0                <1> 	xor 	eax, eax
  2567 00003BFF FEC0                <1> 	inc	al  ; mov ax, 1
  2568                              <1> ;;;
  2569                              <1> 	; UNIX v1 original 'intract' routine... 
  2570                              <1> 	; / interrupt action
  2571                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2572                              <1> 		; bne 1f / no, 1f
  2573                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2574                              <1> 	; 1: / now in user area
  2575                              <1> 		; mov r1,-(sp) / save r1
  2576                              <1> 		; mov u.ttyp,r1 
  2577                              <1> 			; / pointer to tty buffer in control-to r1
  2578                              <1> 		; cmpb 6(r1),$177
  2579                              <1> 			; / is the interrupt char equal to "del"
  2580                              <1> 		; beq 1f / yes, 1f
  2581                              <1> 		; clrb 6(r1) 
  2582                              <1> 		        ; / no, clear the byte 
  2583                              <1> 			; / (must be a quit character)
  2584                              <1> 		; mov (sp)+,r1 / restore r1
  2585                              <1> 		; clr u.quit / clear quit flag
  2586                              <1> 		; bis $20,2(sp) 
  2587                              <1> 		    	; / set trace for quit (sets t bit of 
  2588                              <1> 			; / ps-trace trap)
  2589                              <1> 		; rti   ;  / return from interrupt
  2590                              <1> 	; 1: / interrupt char = del
  2591                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2592                              <1> 			   ; / in the buffer
  2593                              <1> 		; mov (sp)+,r1 / restore r1
  2594                              <1> 		; cmp u.intr,$core / should control be 
  2595                              <1> 				; / transferred to loc core?
  2596                              <1> 		; blo 1f
  2597                              <1> 		; jmp *u.intr / user to do rti yes, 
  2598                              <1> 				; / transfer to loc core
  2599                              <1> 	; 1:
  2600                              <1> 		; sys 1 / exit
  2601                              <1> 
  2602                              <1> sysexit: ; <terminate process>
  2603                              <1> 	; 01/02/2022
  2604                              <1> 	; 01/09/2015
  2605                              <1> 	; 31/08/2015
  2606                              <1> 	; 14/05/2015
  2607                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2608                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2609                              <1> 	;
  2610                              <1> 	; 'sysexit' terminates a process. First each file that
  2611                              <1> 	; the process has opened is closed by 'flose'. The process
  2612                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2613                              <1> 	; searched to find children of the dying process. If any of
  2614                              <1> 	; children are zombies (died by not waited for), they are
  2615                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2616                              <1> 	; dying process's parent. When the parent is found, it is
  2617                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2618                              <1> 	; one of these, the dying process just dies. If it is waiting
  2619                              <1> 	; for a child process to die, it notified that it doesn't 
  2620                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2621                              <1> 	; (waiting to active). It is awakened and put on runq by
  2622                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2623                              <1> 	; it will never be run again but stays around until a 'wait'
  2624                              <1> 	; is completed by it's parent process. If the parent is not
  2625                              <1> 	; found, process just dies. This means 'swap' is called with
  2626                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2627                              <1> 	; to write out the process and 'rswap' reads the new process
  2628                              <1> 	; over the one that dies..i.e., the dying process is 
  2629                              <1> 	; overwritten and destroyed.	
  2630                              <1>  	;
  2631                              <1> 	; Calling sequence:
  2632                              <1> 	;	sysexit or conditional branch.
  2633                              <1> 	; Arguments:
  2634                              <1> 	;	-	
  2635                              <1> 	; ...............................................................
  2636                              <1> 	;	
  2637                              <1> 	; Retro UNIX 8086 v1 modification: 
  2638                              <1> 	;       System call number (=1) is in EAX register.
  2639                              <1> 	;
  2640                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2641                              <1> 	;       registers depending of function details.
  2642                              <1> 	;
  2643                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2644                              <1> 	;
  2645                              <1> ; / terminate process
  2646                              <1> 	; AX = 1
  2647                              <1> 	;dec 	ax ; 0
  2648                              <1> 	; 01/02/2022
  2649 00003C01 48                  <1> 	dec	eax ; 0
  2650 00003C02 66A3[EA6E0000]      <1> 	mov	[u.intr], ax ; 0
  2651                              <1> 		; clr u.intr / clear interrupt control word
  2652                              <1> 		; clr r1 / clear r1
  2653                              <1> 	; AX = 0
  2654                              <1> sysexit_1: ; 1:
  2655                              <1> 	; AX = File descriptor
  2656                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2657                              <1> 		; / Search the whole list
  2658 00003C08 E8550D0000          <1> 	call	fclose
  2659                              <1> 		; jsr r0,fclose / close all files the process opened
  2660                              <1> 	;; ignore error return
  2661                              <1> 		; br .+2 / ignore error return
  2662                              <1> 	;inc	ax
  2663 00003C0D FEC0                <1> 	inc	al
  2664                              <1> 		; inc r1 / increment file descriptor
  2665                              <1> 	;cmp	ax, 10
  2666 00003C0F 3C0A                <1> 	cmp	al, 10
  2667                              <1> 		; cmp r1,$10. / end of u.fp list?
  2668 00003C11 72F5                <1> 	jb	short sysexit_1
  2669                              <1> 		; blt 1b / no, go back
  2670 00003C13 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2671                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2672 00003C1A 88A3[276C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2673                              <1> 		; clrb p.stat-1(r1) / free the process
  2674                              <1> 	;shl	bx, 1
  2675 00003C20 D0E3                <1> 	shl	bl, 1
  2676                              <1> 		; asl r1 / use r1 for index into the below tables
  2677 00003C22 668B8B[C66B0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2678                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2679 00003C29 668B93[E66B0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2680                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2681                              <1> 	;xor 	bx, bx ; 0
  2682 00003C30 30DB                <1> 	xor	bl, bl ; 0
  2683                              <1> 		; clr r2
  2684 00003C32 31F6                <1> 	xor	esi, esi ; 0
  2685                              <1> 		; clr r5 / initialize reg
  2686                              <1> sysexit_2: ; 1:
  2687                              <1> 	        ; / find children of this dying process, 
  2688                              <1> 		; / if they are zombies, free them
  2689                              <1> 	;add	bx, 2
  2690 00003C34 80C302              <1> 	add	bl, 2
  2691                              <1> 		; add $2,r2 / search parent process table 
  2692                              <1> 		          ; / for dying process's name
  2693 00003C37 66398B[E66B0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2694                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2695 00003C3E 7513                <1> 	jne	short sysexit_4
  2696                              <1> 		; bne 3f / no
  2697                              <1> 	;shr	bx, 1
  2698 00003C40 D0EB                <1> 	shr	bl, 1
  2699                              <1> 		; asr r2 / yes, it is a parent
  2700 00003C42 80BB[276C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2701                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2702                              <1> 				     ; / dying process a zombie
  2703 00003C49 7506                <1> 	jne	short sysexit_3 
  2704                              <1> 		; bne 2f / no
  2705 00003C4B 88A3[276C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2706                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2707                              <1> sysexit_3: ; 2:
  2708                              <1> 	;shr	bx, 1
  2709 00003C51 D0E3                <1> 	shl	bl, 1
  2710                              <1> 		; asl r2
  2711                              <1> sysexit_4: ; 3:
  2712                              <1> 		; / search the process name table 
  2713                              <1> 		; / for the dying process's parent
  2714 00003C53 663993[C66B0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2715                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2716 00003C5A 7502                <1> 	jne	short sysexit_5
  2717                              <1> 		; bne 3f / no
  2718 00003C5C 89DE                <1> 	mov	esi, ebx
  2719                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2720                              <1> 		          ; / process # x2) in r5
  2721                              <1> sysexit_5: ; 3:
  2722                              <1> 	;cmp	bx, nproc + nproc
  2723 00003C5E 80FB20              <1> 	cmp	bl, nproc + nproc
  2724                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2725 00003C61 72D1                <1> 	jb	short sysexit_2
  2726                              <1> 		; blt 1b / no, go back
  2727                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2728 00003C63 21F6                <1> 	and	esi, esi ; r5=r1
  2729 00003C65 7431                <1> 	jz	short sysexit_6
  2730                              <1> 		; beq 2f / no parent has been found. 
  2731                              <1> 		       ; / The process just dies
  2732 00003C67 66D1EE              <1> 	shr	si, 1
  2733                              <1> 		; asr r1 / set up index to p.stat
  2734 00003C6A 8A86[276C0000]      <1> 	mov	al, [esi+p.stat-1]
  2735                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2736 00003C70 20C0                <1> 	and	al, al
  2737 00003C72 7424                <1> 	jz	short sysexit_6
  2738                              <1> 		; beq 2f / if its been freed, 2f
  2739 00003C74 3C03                <1> 	cmp	al, 3
  2740                              <1> 		; cmp r2,$3 / is parent a zombie?
  2741 00003C76 7420                <1> 	je	short sysexit_6
  2742                              <1> 		; beq 2f / yes, 2f
  2743                              <1> 	; BH = 0
  2744 00003C78 8A1D[F56E0000]      <1> 	mov	bl, [u.uno]
  2745                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2746 00003C7E C683[276C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2747                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2748                              <1> 	; 05/02/2014
  2749 00003C85 3C01                <1> 	cmp	al, 1 ; SRUN
  2750 00003C87 740F                <1> 	je	short sysexit_6
  2751                              <1> 	;cmp	al, 2
  2752                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2753                              <1> 			  ; / this child to die
  2754                              <1> 	;jne	short sysexit_6	
  2755                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2756                              <1> 	; 05/02/2014
  2757                              <1> 	; p.stat = 2 --> waiting
  2758                              <1> 	; p.stat = 4 --> sleeping
  2759 00003C89 C686[276C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2760                              <1> 	;dec	byte [esi+p.stat-1]
  2761                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2762 00003C90 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2763                              <1> 	; 
  2764                              <1> 	;mov	ebx, runq + 4
  2765                              <1> 		; mov $runq+4,r2 / on the runq
  2766 00003C93 E879120000          <1> 	call	putlu
  2767                              <1> 		; jsr r0, putlu
  2768                              <1> sysexit_6: ; 2:
  2769                              <1> 	; 31/08/2015
  2770                              <1> 		; / the process dies
  2771 00003C98 C605[F56E0000]00    <1> 	mov	byte [u.uno], 0
  2772                              <1> 		; clrb u.uno / put zero as the process number, 
  2773                              <1> 	           ; / so "swap" will
  2774 00003C9F E8A0110000          <1> 	call	swap
  2775                              <1> 		; jsr r0,swap / overwrite process with another process
  2776                              <1> hlt_sys:
  2777                              <1> 	;sti ; 18/01/2014
  2778                              <1> hlts0:
  2779 00003CA4 F4                  <1> 	hlt
  2780 00003CA5 EBFD                <1> 	jmp	short hlts0
  2781                              <1> 		; 0 / and thereby kill it; halt?
  2782                              <1> 
  2783                              <1> 
  2784                              <1> syswait: ; < wait for a processs to die >
  2785                              <1> 	; 12/02/2022
  2786                              <1> 	; 01/02/2022
  2787                              <1> 	; 17/09/2015
  2788                              <1> 	; 02/09/2015
  2789                              <1> 	; 01/09/2015
  2790                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2791                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2792                              <1> 	;
  2793                              <1> 	; 'syswait' waits for a process die. 
  2794                              <1> 	; It works in following way:
  2795                              <1> 	;    1) From the parent process number, the parent's 
  2796                              <1> 	; 	process name is found. The p.ppid table of parent
  2797                              <1> 	;	names is then searched for this process name.
  2798                              <1> 	;	If a match occurs, r2 contains child's process
  2799                              <1> 	;	number. The child status is checked to see if it is
  2800                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2801                              <1> 	;	If it is, the child process is freed and it's name
  2802                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2803                              <1> 	;	If the child is not a zombie, nothing happens and
  2804                              <1> 	;	the search goes on through the p.ppid table until
  2805                              <1> 	;	all processes are checked or a zombie is found.
  2806                              <1> 	;    2) If no zombies are found, a check is made to see if
  2807                              <1> 	;	there are any children at all. If there are none,
  2808                              <1> 	;	an error return is made. If there are, the parent's
  2809                              <1> 	;	status is set to 2 (waiting for child to die),
  2810                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2811                              <1> 	;	is made to wait on the next process.
  2812                              <1> 	;
  2813                              <1> 	; Calling sequence:
  2814                              <1> 	;	?
  2815                              <1> 	; Arguments:
  2816                              <1> 	;	-
  2817                              <1> 	; Inputs: - 
  2818                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2819                              <1> 	; ...............................................................
  2820                              <1> 	;				
  2821                              <1> 	
  2822                              <1> ; / wait for a process to die
  2823                              <1> 
  2824                              <1> syswait_0:
  2825 00003CA7 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2826                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2827 00003CAE D0E3                <1> 	shl	bl, 1
  2828                              <1> 	;shl	bx, 1
  2829                              <1> 		; asl r1 / x2 to get index into p.pid table
  2830 00003CB0 668B83[C66B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2831                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2832 00003CB7 31F6                <1> 	xor	esi, esi
  2833                              <1> 		; clr r2
  2834 00003CB9 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2835                              <1> 	;xor 	cl, cl
  2836                              <1> 		; clr r3 / initialize reg 3
  2837                              <1> syswait_1: ; 1:
  2838                              <1> 	; 12/02/2022
  2839 00003CBB 46                  <1> 	inc	esi
  2840 00003CBC 46                  <1> 	inc	esi
  2841                              <1> 	;add	si, 2
  2842                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2843                              <1> 			  ; / search table of parent processes 
  2844                              <1> 			  ; / for this process name
  2845 00003CBD 663B86[E66B0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2846                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2847                              <1> 			            ; / process number
  2848 00003CC4 7531                <1> 	jne	short syswait_3
  2849                              <1> 		; bne 3f / branch if no match of parent process name
  2850                              <1> 	;inc	cx
  2851 00003CC6 FEC1                <1> 	inc	cl
  2852                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2853                              <1> 	; 12/02/2022
  2854 00003CC8 D1EE                <1> 	shr	esi, 1
  2855                              <1> 	;shr	si, 1
  2856                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2857                              <1> 	; The possible states ('p.stat' values) of a process are:
  2858                              <1> 	;	0 = free or unused
  2859                              <1> 	;	1 = active
  2860                              <1> 	;	2 = waiting for a child process to die
  2861                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2862 00003CCA 80BE[276C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2863                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2864 00003CD1 7522                <1> 	jne	short syswait_2
  2865                              <1> 		; bne 2f / no, skip it
  2866 00003CD3 88BE[276C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2867                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2868                              <1> 	; 12/02/2022
  2869 00003CD9 D1E6                <1> 	shl	esi, 1
  2870                              <1> 	;shl	si, 1
  2871                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2872 00003CDB 0FB786[C66B0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2873 00003CE2 A3[AC6E0000]        <1> 	mov	[u.r0], eax
  2874                              <1> 		; mov p.pid-2(r2),*u.r0 
  2875                              <1> 			      ; / put childs process name in (u.r0)
  2876                              <1> 	;
  2877                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2878                              <1> 	;
  2879                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2880                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2881                              <1> 	; system call loop from the application/program if it calls
  2882                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2883                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2884                              <1> 	;
  2885                              <1> 	; Note: syswait will return with error if there is not a
  2886                              <1> 	;       zombie or running process to wait.	
  2887                              <1> 	;
  2888                              <1> 	;sub	ax, ax
  2889                              <1> 	; 01/02/2022
  2890 00003CE7 29C0                <1> 	sub	eax, eax
  2891 00003CE9 668986[E66B0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2892 00003CF0 E913FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2893                              <1> 	;
  2894                              <1> 	;jmp	sysret
  2895                              <1> 		; br sysret1 / return cause child is dead
  2896                              <1> syswait_2: ; 2:
  2897                              <1> 	; 12/02/2022
  2898 00003CF5 D1E6                <1> 	shl	esi, 1
  2899                              <1> 	;shl	si, 1
  2900                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2901                              <1> syswait_3: ; 3:
  2902 00003CF7 6683FE20            <1> 	cmp	si, nproc+nproc
  2903                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2904 00003CFB 72BE                <1> 	jb	short syswait_1
  2905                              <1> 		; blt 1b / no, continue search
  2906                              <1> 	;and	cx, cx
  2907 00003CFD 20C9                <1> 	and	cl, cl
  2908                              <1> 		; tst r3 / one gets here if there are no children 
  2909                              <1> 		       ; / or children that are still active
  2910                              <1> 	; 30/10/2013
  2911 00003CFF 7515                <1> 	jnz	short syswait_4
  2912                              <1> 	;jz	error
  2913                              <1> 		; beq error1 / there are no children, error
  2914 00003D01 890D[AC6E0000]      <1> 	mov	[u.r0], ecx ; 0
  2915                              <1> 	; 12/02/2022
  2916 00003D07 C705[FB6E0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2916 00003D0F 0000                <1>
  2917                              <1> 			; miscellaneous/other errors
  2918 00003D11 E9D0FDFFFF          <1> 	jmp	error
  2919                              <1> syswait_4:
  2920 00003D16 8A1D[F56E0000]      <1> 	mov	bl, [u.uno]
  2921                              <1> 		; movb u.uno,r1 / there are children so put 
  2922                              <1> 			      ; / parent process number in r1
  2923 00003D1C FE83[276C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2924                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2925                              <1> 				  ; / other children to die
  2926                              <1> 	; 04/11/2013
  2927 00003D22 E81D110000          <1> 	call	swap
  2928                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2929 00003D27 E97BFFFFFF          <1> 	jmp	syswait_0
  2930                              <1> 		; br syswait / wait on next process
  2931                              <1> 
  2932                              <1> sysfork: ; < create a new process >
  2933                              <1> 	; 26/02/2022
  2934                              <1> 	; 25/02/2022
  2935                              <1> 	; 01/02/2022
  2936                              <1> 	; 18/09/2015
  2937                              <1> 	; 04/09/2015
  2938                              <1> 	; 02/09/2015
  2939                              <1> 	; 01/09/2015
  2940                              <1> 	; 28/08/2015
  2941                              <1> 	; 14/05/2015
  2942                              <1> 	; 10/05/2015
  2943                              <1> 	; 09/05/2015
  2944                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2945                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2946                              <1> 	;
  2947                              <1> 	; 'sysfork' creates a new process. This process is referred
  2948                              <1> 	; to as the child process. This new process core image is
  2949                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2950                              <1> 	; distinction is the return location and the fact that (u.r0)
  2951                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2952                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2953                              <1> 	; 'sysfork' works in the following manner: 	
  2954                              <1> 	;    1) The process status table (p.stat) is searched to find
  2955                              <1> 	;	a process number that is unused. If none are found
  2956                              <1> 	;	an error occurs.
  2957                              <1> 	;    2) when one is found, it becomes the child process number
  2958                              <1> 	;	and it's status (p.stat) is set to active.
  2959                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2960                              <1> 	;	character in that tty buffer is cleared.
  2961                              <1> 	;    4) The child process is put on the lowest priority run 
  2962                              <1> 	;	queue via 'putlu'.
  2963                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2964                              <1> 	;	it is a unique number) and is put in the child's unique
  2965                              <1> 	;	identifier; process id (p.pid).
  2966                              <1> 	;    6) The process name of the parent is then obtained and
  2967                              <1> 	;	placed in the unique identifier of the parent process
  2968                              <1> 	;	name is then put in 'u.r0'.	
  2969                              <1> 	;    7) The child process is then written out on disk by
  2970                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2971                              <1> 	;	and the child is born. (The child process is written 
  2972                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2973                              <1> 	;	number.)
  2974                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2975                              <1> 	;    9) The child process name is put in 'u.r0'.
  2976                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2977                              <1> 	;	create the return address for the parent process.
  2978                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2979                              <1> 	;	the parent has opened. For each file the parent has
  2980                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2981                              <1> 	;	to indicate that the child process also has opened
  2982                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2983                              <1> 	;
  2984                              <1> 	; Calling sequence:
  2985                              <1> 	;	from shell ?
  2986                              <1> 	; Arguments:
  2987                              <1> 	;	-
  2988                              <1> 	; Inputs: -
  2989                              <1> 	; Outputs: *u.r0 - child process name
  2990                              <1> 	; ...............................................................
  2991                              <1> 	;	
  2992                              <1> 	; Retro UNIX 8086 v1 modification: 
  2993                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2994                              <1> 	;	= process id of child a parent process returns
  2995                              <1> 	;	= process id of parent when a child process returns
  2996                              <1> 	;
  2997                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  2998                              <1> 	;	in following manner: (with an example: c library, fork)
  2999                              <1> 	;	
  3000                              <1> 	;	1:
  3001                              <1> 	;		sys	fork
  3002                              <1> 	;			br 1f  / child process returns here
  3003                              <1> 	;		bes	2f     / parent process returns here
  3004                              <1> 	;		/ pid of new process in r0
  3005                              <1> 	;		rts	pc
  3006                              <1> 	;	2: / parent process condionally branches here
  3007                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3008                              <1> 	;		rts	pc
  3009                              <1> 	;
  3010                              <1> 	;	1: / child process brances here
  3011                              <1> 	;		clr	r0   / pid = 0 in child process
  3012                              <1> 	;		rts	pc
  3013                              <1> 	;
  3014                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3015                              <1> 	;		// pid = fork();
  3016                              <1> 	;		//
  3017                              <1> 	;		// pid == 0 in child process; 
  3018                              <1> 	;		// pid == -1 means error return
  3019                              <1> 	;		// in child, 
  3020                              <1> 	;		//	parents id is in par_uid if needed
  3021                              <1> 	;		
  3022                              <1> 	;		_fork:
  3023                              <1> 	;			mov	$.fork,eax
  3024                              <1> 	;			int	$0x30
  3025                              <1> 	;			jmp	1f
  3026                              <1> 	;			jnc	2f
  3027                              <1> 	;			jmp	cerror
  3028                              <1> 	;		1:
  3029                              <1> 	;			mov	eax,_par_uid
  3030                              <1> 	;			xor	eax,eax
  3031                              <1> 	;		2:
  3032                              <1> 	;			ret
  3033                              <1> 	;
  3034                              <1> 	;	In Retro UNIX 8086 v1,
  3035                              <1> 	;	'sysfork' returns in following manner:
  3036                              <1> 	;	
  3037                              <1> 	;		mov	ax, sys_fork
  3038                              <1> 	;		mov	bx, offset @f ; routine for child
  3039                              <1> 	;		int	20h
  3040                              <1> 	;		jc	error
  3041                              <1> 	;		
  3042                              <1> 	;	; Routine for parent process here (just after 'jc')
  3043                              <1> 	;		mov	word ptr [pid_of_child], ax
  3044                              <1> 	;		jmp	next_routine_for_parent	
  3045                              <1> 	;
  3046                              <1> 	;	@@: ; routine for child process here				
  3047                              <1> 	;		....	
  3048                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3049                              <1> 	;	       for child process by using BX input.
  3050                              <1> 	;	      (at first, parent process will return then 
  3051                              <1> 	;	      child process will return -after swapped in-
  3052                              <1> 	;	      'syswait' is needed in parent process
  3053                              <1> 	;	      if return from child process will be waited for.)
  3054                              <1> 	;	  				
  3055                              <1> 	
  3056                              <1> ; / create a new process
  3057                              <1> 	; EBX = return address for child process 
  3058                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3059 00003D2C 31F6                <1> 	xor 	esi, esi
  3060                              <1> 		; clr r1
  3061                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3062 00003D2E 46                  <1> 	inc	esi
  3063                              <1> 		; inc r1
  3064 00003D2F 80BE[276C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3065                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3066 00003D36 760B                <1> 	jna	short sysfork_2	
  3067                              <1> 		; beq 1f / it's unused so branch
  3068 00003D38 6683FE10            <1> 	cmp	si, nproc
  3069                              <1> 		; cmp r1,$nproc / all processes checked
  3070 00003D3C 72F0                <1> 	jb	short sysfork_1
  3071                              <1> 		; blt 1b / no, branch back
  3072                              <1> 	;
  3073                              <1> 	; Retro UNIX 8086 v1. modification:
  3074                              <1> 	;	Parent process returns from 'sysfork' to address 
  3075                              <1> 	;	which is just after 'sysfork' system call in parent
  3076                              <1> 	;	process. Child process returns to address which is put
  3077                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3078                              <1> 	;
  3079                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3080                              <1> 		               ; / to old process return
  3081                              <1> 		; br error1 / no room for a new process
  3082                              <1> sysfork_err:
  3083 00003D3E E9A3FDFFFF          <1> 	jmp	error
  3084                              <1> sysfork_2: ; 1:
  3085 00003D43 E88CF0FFFF          <1> 	call	allocate_page
  3086                              <1> 	;jc	error
  3087                              <1> 	; 01/02/2022
  3088 00003D48 72F4                <1> 	jc	short sysfork_err
  3089 00003D4A 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3090                              <1> 	; Retro UNIX 386 v1 modification!
  3091 00003D4B E87DF2FFFF          <1> 	call	duplicate_page_dir
  3092                              <1> 		; EAX = New page directory 
  3093 00003D50 7308                <1> 	jnc	short sysfork_3
  3094 00003D52 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3095 00003D53 E844F2FFFF          <1> 	call 	deallocate_page
  3096                              <1> 	;jmp	error
  3097                              <1> 	; 01/02/2022
  3098 00003D58 EBE4                <1> 	jmp	short sysfork_err
  3099                              <1> sysfork_3:
  3100                              <1> 	; Retro UNIX 386 v1 modification !
  3101 00003D5A 56                  <1> 	push	esi
  3102 00003D5B E85B110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3103                              <1> 		      ; and interrupt return components (for IRET)
  3104 00003D60 8705[FF6E0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3105 00003D66 A3[036F0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3106 00003D6B 5E                  <1> 	pop	esi
  3107 00003D6C 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3108                              <1> 		; [u.usp] = esp
  3109 00003D6D 89F7                <1> 	mov	edi, esi
  3110                              <1> 	;shl	di, 2
  3111                              <1> 	; 12/02/2022
  3112 00003D6F C1E702              <1> 	shl	edi, 2
  3113 00003D72 8987[346C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3114 00003D78 A3[F66E0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3115                              <1> 	; 28/08/2015
  3116 00003D7D 0FB605[F56E0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3117                              <1> 		; movb u.uno,-(sp) / save parent process number
  3118 00003D84 89C7                <1> 	mov	edi, eax
  3119 00003D86 50                  <1>         push	eax ; ** 
  3120 00003D87 8A87[076C0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3121                              <1> 	; 18/09/2015
  3122 00003D8D 8886[076C0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3123                              <1> 	; 26/02/2022 (p.waitc is not used)
  3124                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3125                              <1> 	; 25/02/2022 (BugFix)
  3126                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3127                              <1> 	;			   ; ah - reset child's wait channel	
  3128 00003D93 89F0                <1> 	mov	eax, esi
  3129 00003D95 A2[F56E0000]        <1> 	mov	[u.uno], al ; child process number
  3130                              <1> 		;movb r1,u.uno / set child process number to r1
  3131 00003D9A FE86[276C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3132                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3133                              <1> 				  ; / process to active status
  3134                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3135                              <1> 			      ; / control tty buffer in r2
  3136                              <1>                 ; beq 2f / branch, if no such tty assigned
  3137                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3138                              <1> 	; 2:
  3139 00003DA0 53                  <1> 	push	ebx  ; * return address for the child process
  3140                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3141                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3142                              <1> 		; mov $runq+4,r2
  3143 00003DA1 E86B110000          <1> 	call	putlu 
  3144                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3145                              <1> 			   ; / run queue
  3146                              <1> 	; 12/02/2022
  3147 00003DA6 D1E6                <1> 	shl	esi, 1
  3148                              <1> 	;shl	si, 1
  3149                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3150                              <1> 		       ; / into p.pid table
  3151 00003DA8 66FF05[986E0000]    <1> 	inc	word [mpid]
  3152                              <1> 		; inc mpid / increment m.pid; get a new process name
  3153 00003DAF 66A1[986E0000]      <1> 	mov	ax, [mpid]
  3154 00003DB5 668986[C66B0000]    <1> 	mov	[esi+p.pid-2], ax
  3155                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3156                              <1> 				    ; / in child process' name slot
  3157 00003DBC 5A                  <1> 	pop	edx  ; * return address for the child process
  3158                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3159 00003DBD 5B                  <1>   	pop	ebx  ; **
  3160                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3161                              <1> 		; movb (sp),r2 / put parent process number in r2
  3162                              <1> 	; 01/02/2022
  3163 00003DBE D0E3                <1> 	shl	bl, 1
  3164                              <1> 	;shl 	bx, 1
  3165                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3166                              <1> 	; ebx <= 32
  3167                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3168 00003DC0 668B83[C66B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3169                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3170                              <1> 				   ; / process
  3171 00003DC7 668986[E66B0000]    <1> 	mov	[esi+p.ppid-2], ax
  3172                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3173                              <1> 			  ; / in parent process slot for child
  3174 00003DCE A3[AC6E0000]        <1> 	mov	[u.r0], eax	
  3175                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3176                              <1> 			     ; / at location where r0 was saved
  3177 00003DD3 8B2D[A46E0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3178 00003DD9 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3179                              <1> 			   ; * return address for the child process
  3180                              <1> 		; mov $sysret1,-(sp) /
  3181                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3182                              <1> 			      ; / user is swapped out
  3183                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3184                              <1> 	; 04/09/2015 - 01/09/2015
  3185                              <1> 	; [u.usp] = esp
  3186 00003DDC 68[063B0000]        <1> 	push	sysret ; ***
  3187 00003DE1 8925[A86E0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3188                              <1> 			     ; (for child process)	
  3189 00003DE7 31C0                <1> 	xor 	eax, eax
  3190 00003DE9 66A3[DC6E0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3191                              <1> 	;
  3192 00003DEF E8C7100000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3193                              <1> 		;jsr r0,wswap / put child process out on drum
  3194                              <1> 		;jsr r0,unpack / unpack user stack
  3195                              <1> 		;mov u.usp,sp / restore user stack pointer
  3196                              <1> 		; tst (sp)+ / bump stack pointer
  3197                              <1> 	; Retro UNIX 386 v1 modification !
  3198 00003DF4 58                  <1> 	pop	eax ; ***
  3199                              <1> 	;shl	bx, 1
  3200                              <1> 	; 01/02/2022
  3201 00003DF5 D0E3                <1> 	shl	bl, 1 
  3202                              <1> 		; ebx <= 64
  3203 00003DF7 8B83[346C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3204 00003DFD E8E2100000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3205                              <1> 		      ; registers and return address (for IRET)
  3206                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3207 00003E02 0FB705[986E0000]    <1>         movzx   eax, word [mpid]
  3208 00003E09 A3[AC6E0000]        <1> 	mov	[u.r0], eax
  3209                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3210                              <1> 			       ; / where r0 was saved
  3211                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3212                              <1> 			       ; / process return
  3213                              <1> 	;xor	ebx, ebx
  3214 00003E0E 31F6                <1> 	xor     esi, esi
  3215                              <1> 		;clr r1
  3216                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3217                              <1> 	      ; / opened by the parent process
  3218                              <1> 	; 01/09/2015
  3219                              <1> 	;xor	bh, bh
  3220                              <1> 	;mov 	bl, [esi+u.fp]
  3221 00003E10 8A86[B26E0000]      <1> 	mov 	al, [esi+u.fp]
  3222                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3223                              <1>         ;or	bl, bl
  3224 00003E16 08C0                <1> 	or	al, al
  3225 00003E18 740C                <1> 	jz	short sysfork_5	
  3226                              <1> 		; beq 2f / file has not been opened by parent, 
  3227                              <1> 		       ; / so branch
  3228 00003E1A B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3229 00003E1C F6E4                <1> 	mul	ah
  3230                              <1> 	;;movzx	ebx, ax
  3231                              <1> 	;mov	bx, ax
  3232 00003E1E 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3233                              <1> 	;shl	bx, 3
  3234                              <1> 		; asl r2 / multiply by 8
  3235                              <1>        		; asl r2 / to get index into fsp table
  3236                              <1>        		; asl r2
  3237 00003E20 FE83[766C0000]      <1>   	inc     byte [ebx+fsp-2]
  3238                              <1> 		; incb fsp-2(r2) / increment number of processes
  3239                              <1> 			     ; / using file, because child will now be
  3240                              <1> 			     ; / using this file
  3241                              <1> sysfork_5: ; 2:
  3242 00003E26 46                  <1>         inc     esi
  3243                              <1> 		; inc r1 / get next open file
  3244 00003E27 6683FE0A            <1>         cmp     si, 10
  3245                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3246                              <1> 			    ; / can be opened
  3247 00003E2B 72E3                <1> 	jb	short sysfork_4	
  3248                              <1> 		; blt 1b / check next entry
  3249 00003E2D E9D4FCFFFF          <1> 	jmp	sysret
  3250                              <1> 		; br sysret1
  3251                              <1> 
  3252                              <1> sysread: ; < read from file >
  3253                              <1> 	; 27/02/2022
  3254                              <1> 	; 01/02/2022
  3255                              <1> 	; 13/05/2015
  3256                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3257                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3258                              <1> 	;
  3259                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3260                              <1> 	; characters to be read. If finds the file from the file
  3261                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3262                              <1> 	; is returned from a successful open call (sysopen).
  3263                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3264                              <1> 	; is read into core via 'readi'.
  3265                              <1> 	;
  3266                              <1> 	; Calling sequence:
  3267                              <1> 	;	sysread; buffer; nchars
  3268                              <1> 	; Arguments:
  3269                              <1> 	;	buffer - location of contiguous bytes where 
  3270                              <1> 	;		 input will be placed.
  3271                              <1> 	;	nchars - number of bytes or characters to be read.
  3272                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3273                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3274                              <1> 	; ...............................................................
  3275                              <1> 	;				
  3276                              <1> 	; Retro UNIX 8086 v1 modification: 
  3277                              <1> 	;       'sysread' system call has three arguments; so,
  3278                              <1> 	;	* 1st argument, file descriptor is in BX register
  3279                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3280                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3281                              <1> 	;
  3282                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3283                              <1> 	;	to the user with number of bytes read. 
  3284                              <1> 	;
  3285 00003E32 E840000000          <1> 	call	rw1
  3286                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3287                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3288                              <1>        	; 27/02/2022
  3289 00003E37 7239                <1> 	jc	short sysread_err
  3290 00003E39 F6C480              <1> 	test	ah, 80h
  3291                              <1> 		; tst r1 / negative i-number?
  3292                              <1> 	;jnz	error
  3293                              <1> 		; ble error1 / yes, error 1 to read
  3294                              <1> 			   ; / it should be positive
  3295                              <1> 	; 01/02/2022
  3296                              <1> 	;jnz	short rw_error
  3297                              <1> 	;27/02/2022
  3298 00003E3C 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3299                              <1> 	;
  3300 00003E3E E833150000          <1> 	call	readi
  3301                              <1> 		; jsr r0,readi / read data into core
  3302 00003E43 EB14                <1> 	jmp	short rw0
  3303                              <1> 		; br 1f
  3304                              <1> 
  3305                              <1> syswrite: ; < write to file >
  3306                              <1> 	; 27/02/2022
  3307                              <1> 	; 01/02/2022
  3308                              <1> 	; 13/05/2015
  3309                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3310                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3311                              <1> 	;
  3312                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3313                              <1> 	; and the number of characters to write. If finds the file
  3314                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3315                              <1> 	; descriptor is returned from a successful open or create call
  3316                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3317                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3318                              <1> 	;
  3319                              <1> 	; Calling sequence:
  3320                              <1> 	;	syswrite; buffer; nchars
  3321                              <1> 	; Arguments:
  3322                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3323                              <1> 	;	nchars - number of characters to be written.
  3324                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3325                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3326                              <1> 	; ...............................................................
  3327                              <1> 	;				
  3328                              <1> 	; Retro UNIX 8086 v1 modification: 
  3329                              <1> 	;       'syswrite' 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 written. 
  3336                              <1> 	;
  3337 00003E45 E82D000000          <1> 	call	rw1
  3338                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3339                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3340                              <1> 	; 01/02/2022
  3341                              <1> 	;jnc	short syswrite_1
  3342                              <1> ;rw_error:
  3343                              <1> 	;jmp	error
  3344                              <1> 	; 27/02/2022
  3345 00003E4A 7226                <1> 	jc	short short syswrite_err
  3346                              <1> syswrite_1:
  3347 00003E4C F6C480              <1>         test	ah, 80h
  3348                              <1> 		; tst r1 / positive i-number ?
  3349 00003E4F 7417                <1>         jz	short rw3 ; 13/05/2015
  3350                              <1> 	;jz	error
  3351                              <1> 		; bge error1 / yes, error 1 
  3352                              <1> 			   ; / negative i-number means write
  3353 00003E51 66F7D8              <1> 	neg	ax
  3354                              <1> 		; neg r1 / make it positive
  3355 00003E54 E80B170000          <1> 	call	writei
  3356                              <1>         	; jsr r0,writei / write data
  3357                              <1> rw0: ; 1:
  3358 00003E59 A1[D46E0000]        <1>         mov	eax, [u.nread]
  3359 00003E5E A3[AC6E0000]        <1> 	mov	[u.r0], eax
  3360                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3361                              <1> 				  ; / into (u.r0)
  3362 00003E63 E99EFCFFFF          <1> 	jmp	sysret
  3363                              <1>         	; br sysret1
  3364                              <1> rw3: 
  3365                              <1> 	; 13/05/2015
  3366 00003E68 C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3366 00003E70 0000                <1>
  3367                              <1> 	;stc
  3368                              <1> 	;retn
  3369                              <1> 	; 27/02/2022 (BugFix)
  3370                              <1> sysread_err:
  3371                              <1> syswrite_err:
  3372 00003E72 E96FFCFFFF          <1> 	jmp	error
  3373                              <1> 
  3374                              <1> rw1:	
  3375                              <1> 	; 14/05/2015
  3376                              <1> 	; 13/05/2015
  3377                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3378                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3379                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3380                              <1> 	;
  3381                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3382                              <1> 				;(in the user's virtual memory space)
  3383                              <1> 	;mov	[u.count], edx 
  3384                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3385                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3386                              <1> 	;;mov	eax, ebx ; file descriptor
  3387                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3388                              <1> 		             ; / (index to u.fp table) in r1
  3389                              <1> 	; 13/05/2015
  3390 00003E77 C705[AC6E0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3390 00003E7F 0000                <1>
  3391                              <1> 	;
  3392                              <1> 	;; call	getf
  3393                              <1>         ; eBX = File descriptor
  3394 00003E81 E81F0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3395                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3396                              <1> 	; AX = I-number of the file ; negative i-number means write
  3397                              <1> 	; 13/05/2015
  3398 00003E86 6683F801            <1> 	cmp 	ax, 1
  3399 00003E8A 7217                <1> 	jb	short rw2
  3400                              <1> 	;
  3401 00003E8C 890D[CC6E0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3402                              <1> 				;(in the user's virtual memory space)
  3403 00003E92 8915[D06E0000]      <1> 	mov	[u.count], edx 
  3404                              <1> 	; 14/05/2015
  3405 00003E98 C705[FB6E0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3405 00003EA0 0000                <1>
  3406 00003EA2 C3                  <1> 	retn
  3407                              <1>         	; rts r0
  3408                              <1> rw2:
  3409                              <1> 	; 13/05/2015
  3410 00003EA3 C705[FB6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3410 00003EAB 0000                <1>
  3411 00003EAD C3                  <1> 	retn
  3412                              <1> 
  3413                              <1> sysopen: ;<open file>
  3414                              <1> 	; 12/02/2022
  3415                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3416                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3417                              <1> 	;
  3418                              <1> 	; 'sysopen' opens a file in following manner:
  3419                              <1> 	;    1) The second argument in a sysopen says whether to
  3420                              <1> 	;	open the file ro read (0) or write (>0).
  3421                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3422                              <1> 	;    3) The file is opened by 'iopen'.
  3423                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3424                              <1> 	;	and the user's open file list - u.fp.
  3425                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3426                              <1> 	;	b) An entry for the file is created in the fsp table.
  3427                              <1> 	;	c) The number of this entry is put on u.fp list.
  3428                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3429                              <1> 	;	   to by u.r0.
  3430                              <1> 	;
  3431                              <1> 	; Calling sequence:
  3432                              <1> 	;	sysopen; name; mode
  3433                              <1> 	; Arguments:
  3434                              <1> 	;	name - file name or path name
  3435                              <1> 	;	mode - 0 to open for reading
  3436                              <1> 	;	       1 to open for writing
  3437                              <1> 	; Inputs: (arguments)
  3438                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3439                              <1> 	;		  is put into r0's location on the stack.	
  3440                              <1> 	; ...............................................................
  3441                              <1> 	;				
  3442                              <1> 	; Retro UNIX 8086 v1 modification: 
  3443                              <1> 	;       'sysopen' system call has two arguments; so,
  3444                              <1> 	;	* 1st argument, name is pointed to by BX register
  3445                              <1> 	;	* 2nd argument, mode is in CX register
  3446                              <1> 	;
  3447                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3448                              <1> 	;	to the user with the file descriptor/number 
  3449                              <1> 	;	(index to u.fp list).
  3450                              <1> 	;
  3451                              <1> 	;call	arg2
  3452                              <1> 	; * name - 'u.namep' points to address of file/path name
  3453                              <1> 	;          in the user's program segment ('u.segmnt')
  3454                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3455                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3456                              <1> 	;          which is on top of stack.
  3457                              <1> 	;
  3458                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3459                              <1> 	;
  3460                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3461                              <1> 
  3462 00003EAE 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  3463                              <1> 	;push	cx
  3464 00003EB4 51                  <1> 	push	ecx ; 12/02/2022
  3465 00003EB5 E81E0B0000          <1> 	call	namei
  3466                              <1> 		; jsr r0,namei / i-number of file in r1
  3467                              <1>      	;and	ax, ax
  3468                              <1> 	;jz	error ; File not found
  3469 00003EBA 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3470                              <1> 	;jc	error ; 27/05/2013
  3471                              <1> 		; br  error2 / file not found
  3472                              <1>    	;pop	dx ; mode
  3473                              <1> 	;push	dx
  3474                              <1> 	; 12/02/2022
  3475                              <1> 	;pop	edx ; * ; mode
  3476                              <1> 	;push	edx ; *
  3477 00003EBC 8B1424              <1> 	mov	edx, [esp] ; *
  3478                              <1> 	; edx = open mode (0 or 1)
  3479                              <1> 	;or	dx, dx
  3480 00003EBF 08D2                <1> 	or	dl, dl
  3481                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3482                              <1> 		         ; / 0 means, open for read)
  3483 00003EC1 7403                <1> 	jz	short sysopen_0
  3484                              <1> 		; beq 1f / yes, leave i-number positive
  3485                              <1> syscreat_0: 
  3486                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3487 00003EC3 66F7D8              <1> 	neg	ax
  3488                              <1>         	; neg r1 / open for writing so make i-number negative
  3489                              <1> sysopen_0: ;1:
  3490 00003EC6 E85B1A0000          <1> 	call	iopen
  3491                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3492 00003ECB 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3493                              <1> 	;and	dx, dx
  3494 00003ECC 20D2                <1> 	and	dl, dl
  3495                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3496 00003ECE 7403                <1> 	jz	short sysopen_2
  3497                              <1>         	; beq op1 / is open for read op1
  3498                              <1> sysopen_1: ;op0:
  3499 00003ED0 66F7D8              <1> 	neg	ax
  3500                              <1>         	; neg r1 
  3501                              <1> 		     ;/ make i-number positive if open for writing [???]
  3502                              <1> 	;; NOTE: iopen always make i-number positive.
  3503                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3504                              <1> sysopen_2: ;op1:
  3505 00003ED3 31F6                <1>         xor     esi, esi
  3506                              <1>         	; clr r2 / clear registers
  3507 00003ED5 31DB                <1>         xor     ebx, ebx
  3508                              <1> 		; clr r3
  3509                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3510 00003ED7 389E[B26E0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3511                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3512 00003EDD 7625                <1>         jna	short sysopen_4
  3513                              <1> 		; beq 1f / if byte in list is 0 branch
  3514 00003EDF 46                  <1>         inc     esi
  3515                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3516 00003EE0 6683FE0A            <1>         cmp     si, 10
  3517                              <1> 		; cmp r2,$10. / reached end of list?
  3518 00003EE4 72F1                <1> 	jb	short sysopen_3
  3519                              <1> 		; blt 1b / no, go back
  3520                              <1> toomanyf:
  3521                              <1> 	; 14/05/2015
  3522 00003EE6 C705[FB6E0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3522 00003EEE 0000                <1>
  3523 00003EF0 E9F1FBFFFF          <1> 	jmp	error
  3524                              <1>         	; br error2 / yes, error (no files open)
  3525                              <1> fnotfound: 
  3526                              <1> 	; 14/05/2015
  3527 00003EF5 C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3527 00003EFD 0000                <1>
  3528 00003EFF E9E2FBFFFF          <1> 	jmp	error
  3529                              <1> 
  3530                              <1> sysopen_4: ; 1:
  3531 00003F04 6683BB[786C0000]00  <1>         cmp     word [ebx+fsp], 0
  3532                              <1> 		; tst fsp(r3) / scan fsp entries
  3533 00003F0C 7610                <1>         jna     short sysopen_5
  3534                              <1> 		; beq 1f / if 0 branch
  3535                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3536 00003F0E 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3537                              <1> 		; add $8.,r3 / add 8 to r3 
  3538                              <1> 			; / to bump it to next entry mfsp table
  3539 00003F12 6681FBF401          <1>         cmp     bx, nfiles*10
  3540                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3541 00003F17 72EB                <1> 	jb	short sysopen_4
  3542                              <1>        		; blt 1b / no, back
  3543 00003F19 E9C8FBFFFF          <1> 	jmp	error
  3544                              <1>         	; br error2 / yes, error
  3545                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3546 00003F1E 668983[786C0000]    <1>         mov     [ebx+fsp], ax
  3547                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3548                              <1> 			; / into next available entry in fsp table,
  3549                              <1> 	; 12/02/2022
  3550                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3551                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3552                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3553                              <1> 	;xor	edi, edi
  3554                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3555                              <1> 	;	; clr fsp+4(r3)
  3556                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3557                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3558 00003F25 31C0                <1> 	xor	eax, eax
  3559 00003F27 8983[7C6C0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3560 00003F2D 668983[806C0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3561                              <1> 
  3562 00003F34 66A1[906E0000]      <1> 	mov	ax, [cdev]
  3563 00003F3A 668983[7A6C0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3564                              <1> 
  3565 00003F41 89D8                <1>   	mov	eax, ebx
  3566 00003F43 B30A                <1> 	mov	bl, 10
  3567 00003F45 F6F3                <1> 	div	bl 
  3568                              <1> 		; asr r3
  3569                              <1> 		; asr r3 / divide by 8 
  3570                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3571 00003F47 FEC0                <1> 	inc	al
  3572                              <1>         	; inc r3 / add 1 to get fsp entry number
  3573 00003F49 8886[B26E0000]      <1>         mov     [esi+u.fp], al
  3574                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3575                              <1> 			; / next available slot in u.fp list
  3576 00003F4F 8935[AC6E0000]      <1>         mov     [u.r0], esi
  3577                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3578                              <1> 			     ; / into r0 loc on stack
  3579 00003F55 E9ACFBFFFF          <1>         jmp	sysret
  3580                              <1> 		; br sysret2
  3581                              <1> 
  3582                              <1> 	;
  3583                              <1> 	; 'fsp' table (10 bytes/entry)
  3584                              <1> 	; bit 15				   bit 0
  3585                              <1> 	; ---|-------------------------------------------
  3586                              <1> 	; r/w|		i-number of open file
  3587                              <1> 	; ---|-------------------------------------------
  3588                              <1> 	;		   device number
  3589                              <1> 	; -----------------------------------------------
  3590                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3591                              <1> 	; -----------------------------------------------
  3592                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3593                              <1> 	; ----------------------|------------------------
  3594                              <1> 	;  flag that says file 	| number of processes
  3595                              <1> 	;   has been deleted	| that have file open 
  3596                              <1> 	; ----------------------|------------------------
  3597                              <1> 	;
  3598                              <1> 
  3599                              <1> syscreat: ; < create file >
  3600                              <1> 	; 12/02/2022
  3601                              <1> 	; 01/02/2022
  3602                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3603                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3604                              <1> 	;
  3605                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3606                              <1> 	; u.namep points to name of the file and mode is put
  3607                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3608                              <1> 	; If the file aready exists, it's mode and owner remain 
  3609                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3610                              <1> 	; did not exist, an i-node is created with the new mode via
  3611                              <1> 	; 'maknod' whether or not the file already existed, it is
  3612                              <1> 	; open for writing. The fsp table is then searched for a free
  3613                              <1> 	; entry. When a free entry is found, proper data is placed
  3614                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3615                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3616                              <1> 	; is put in the user's r0. 			
  3617                              <1> 	;
  3618                              <1> 	; Calling sequence:
  3619                              <1> 	;	syscreate; name; mode
  3620                              <1> 	; Arguments:
  3621                              <1> 	;	name - name of the file to be created
  3622                              <1> 	;	mode - mode of the file to be created
  3623                              <1> 	; Inputs: (arguments)
  3624                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3625                              <1> 	;		   (the file descriptor of new file)
  3626                              <1> 	; ...............................................................
  3627                              <1> 	;				
  3628                              <1> 	; Retro UNIX 8086 v1 modification: 
  3629                              <1> 	;       'syscreate' system call has two arguments; so,
  3630                              <1> 	;	* 1st argument, name is pointed to by BX register
  3631                              <1> 	;	* 2nd argument, mode is in CX register
  3632                              <1> 	;
  3633                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3634                              <1> 	;	to the user with the file descriptor/number 
  3635                              <1> 	;	(index to u.fp list).
  3636                              <1> 	;
  3637                              <1> 	;call	arg2
  3638                              <1> 	; * name - 'u.namep' points to address of file/path name
  3639                              <1> 	;          in the user's program segment ('u.segmnt')
  3640                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3641                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3642                              <1> 	;          which is on top of stack.
  3643                              <1> 	;
  3644                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3645                              <1> 			    ; / on stack
  3646 00003F5A 891D[C46E0000]      <1> 	mov	[u.namep], ebx ; file name address
  3647                              <1> 	;push	cx ; mode
  3648                              <1> 	; 01/02/2022
  3649 00003F60 51                  <1> 	push	ecx ; mode
  3650 00003F61 E8720A0000          <1> 	call 	namei        	
  3651                              <1> 		; jsr r0,namei / get the i-number
  3652                              <1>         ;and	ax, ax
  3653                              <1> 	;jz	short syscreat_2	       	
  3654 00003F66 721B                <1> 	jc	short syscreat_2
  3655                              <1> 		; br  2f / if file doesn't exist 2f
  3656                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3657                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3658 00003F68 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3659                              <1>         ;jb	syscreat_0 ; yes
  3660                              <1> 	; 02/02/2022
  3661 00003F6C 7305                <1> 	jnb	short syscreat_1
  3662 00003F6E E950FFFFFF          <1> 	jmp	syscreat_0
  3663                              <1> syscreat_1:
  3664 00003F73 66F7D8              <1> 	neg 	ax
  3665                              <1>         	; neg r1 / if file already exists make i-number 
  3666                              <1> 		       ; / negative (open for writing)
  3667 00003F76 E8AB190000          <1> 	call	iopen
  3668                              <1>         	; jsr r0,iopen /
  3669 00003F7B E84E130000          <1> 	call	itrunc
  3670                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3671                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3672                              <1> 	; 01/02/2022
  3673 00003F80 59                  <1> 	pop	ecx ; mode
  3674                              <1> 	; 12/02/2022
  3675 00003F81 EB0E                <1> 	jmp	short syscreat_3
  3676                              <1>         ;jmp	sysopen_1
  3677                              <1>         	; br op0
  3678                              <1> syscreat_2: ; 2: / file doesn't exist
  3679                              <1> 	; 01/02/2022
  3680 00003F83 58                  <1> 	pop	eax ; mode
  3681                              <1> 	;pop	ax
  3682                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3683 00003F84 30E4                <1> 	xor	ah, ah	
  3684                              <1>         	; bic $!377,r1 / clear upper byte
  3685 00003F86 E8150D0000          <1> 	call 	maknod
  3686                              <1>         	; jsr r0,maknod / make an i-node for this file
  3687 00003F8B 66A1[DE6E0000]      <1> 	mov	ax, [u.dirbuf]
  3688                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3689                              <1> 			        ; / for this new file in r1
  3690                              <1> syscreat_3:
  3691 00003F91 E93AFFFFFF          <1>         jmp     sysopen_1
  3692                              <1>         	; br op0 / open the file
  3693                              <1> 
  3694                              <1> sysmkdir: ; < make directory >
  3695                              <1> 	; 01/02/2022
  3696                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3697                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3698                              <1> 	;
  3699                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3700                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3701                              <1> 	; The special entries '.' and '..' are not present.
  3702                              <1> 	; Errors are indicated if the directory already exists or		
  3703                              <1> 	; user is not the super user. 
  3704                              <1> 	;
  3705                              <1> 	; Calling sequence:
  3706                              <1> 	;	sysmkdir; name; mode
  3707                              <1> 	; Arguments:
  3708                              <1> 	;	name - points to the name of the directory
  3709                              <1> 	;	mode - mode of the directory
  3710                              <1> 	; Inputs: (arguments)
  3711                              <1> 	; Outputs: -
  3712                              <1> 	;    (sets 'directory' flag to 1; 
  3713                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3714                              <1> 	; ...............................................................
  3715                              <1> 	;				
  3716                              <1> 	; Retro UNIX 8086 v1 modification: 
  3717                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3718                              <1> 	;	* 1st argument, name is pointed to by BX register
  3719                              <1> 	;	* 2nd argument, mode is in CX register
  3720                              <1> 		
  3721                              <1> ; / make a directory
  3722                              <1> 	
  3723                              <1> 	;call	arg2
  3724                              <1> 	; * name - 'u.namep' points to address of file/path name
  3725                              <1> 	;          in the user's program segment ('u.segmnt')
  3726                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3727                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3728                              <1> 	;          which is on top of stack.
  3729                              <1> 
  3730                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3731                              <1> 			    ; / on stack
  3732 00003F96 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  3733                              <1> 	;push	cx ; mode
  3734                              <1> 	; 01/02/2022
  3735 00003F9C 51                  <1> 	push	ecx ; mode
  3736 00003F9D E8360A0000          <1> 	call	namei
  3737                              <1>         	; jsr r0,namei / get the i-number
  3738                              <1>         	;     br .+4 / if file not found branch around error
  3739                              <1>         ;xor 	ax, ax
  3740                              <1> 	;jnz	error
  3741 00003FA2 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3742                              <1> 	;jnc	error	
  3743                              <1> 		; br  error2 / directory already exists (error)
  3744 00003FA4 803D[F26E0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3745                              <1>         	;tstb u.uid / is user the super user
  3746                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3747                              <1> 	;;jna	error
  3748                              <1> 	; 01/02/2022 (BugFix)
  3749 00003FAB 7721                <1> 	ja	short dir_access_err
  3750                              <1>         	;bne error2 / no, not allowed
  3751                              <1> 	;pop	ax
  3752                              <1> 	; 01/02/2022
  3753 00003FAD 58                  <1> 	pop	eax ; mode
  3754                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3755 00003FAE 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3756                              <1>         	;bic $!317,r1 / all but su and ex
  3757                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3758 00003FB2 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3759                              <1>         	;bis $40000,r1 / directory flag
  3760 00003FB5 E8E60C0000          <1> 	call	maknod
  3761                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3762                              <1> sysclose_sysret: ; 01/02/2022
  3763 00003FBA E947FBFFFF          <1> 	jmp	sysret
  3764                              <1>         	;br sysret2 /
  3765                              <1> dir_exists:
  3766                              <1> 	; 14/05/2015
  3767 00003FBF C705[FB6E0000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3767 00003FC7 0000                <1>
  3768 00003FC9 E918FBFFFF          <1> 	jmp	error
  3769                              <1> dir_access_err:
  3770                              <1> 	; 14/05/2015
  3771 00003FCE C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3771 00003FD6 0000                <1>
  3772 00003FD8 E909FBFFFF          <1> 	jmp	error
  3773                              <1> 
  3774                              <1> sysclose: ;<close file>
  3775                              <1> 	; 01/02/2022
  3776                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3777                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3778                              <1> 	;
  3779                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3780                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3781                              <1> 	; is put in r1 and 'fclose' is called.
  3782                              <1> 	;
  3783                              <1> 	; Calling sequence:
  3784                              <1> 	;	sysclose
  3785                              <1> 	; Arguments:
  3786                              <1> 	;	-  
  3787                              <1> 	; Inputs: *u.r0 - file descriptor
  3788                              <1> 	; Outputs: -
  3789                              <1> 	; ...............................................................
  3790                              <1> 	;				
  3791                              <1> 	; Retro UNIX 8086 v1 modification:
  3792                              <1> 	;	 The user/application program puts file descriptor
  3793                              <1> 	;        in BX register as 'sysclose' system call argument.
  3794                              <1> 	; 	 (argument transfer method 1)
  3795                              <1> 
  3796                              <1> 	; / close the file
  3797                              <1> 	
  3798 00003FDD 89D8                <1> 	mov 	eax, ebx
  3799 00003FDF E87E090000          <1> 	call 	fclose
  3800                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3801                              <1> 		; jsr r0,fclose / close the file
  3802                              <1>                	; br error2 / unknown file descriptor
  3803                              <1> 		; br sysret2
  3804                              <1> 	; 14/05/2015
  3805                              <1> 	;jnc	sysret
  3806                              <1> 	; 01/02/2022
  3807 00003FE4 73D4                <1> 	jnc	short sysclose_sysret
  3808 00003FE6 C705[FB6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3808 00003FEE 0000                <1>
  3809 00003FF0 E9F1FAFFFF          <1> 	jmp	error
  3810                              <1> 
  3811                              <1> sysemt:
  3812                              <1> 	; 23/02/2022
  3813                              <1> 	; 01/02/2022
  3814                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3815                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3816                              <1> 	;
  3817                              <1> 	; Retro UNIX 8086 v1 modification: 
  3818                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3819                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3820                              <1> 	;
  3821                              <1> 	; Retro UNIX 8086 v1 feature only!
  3822                              <1> 	;	Using purpose: Kernel will start without time-out
  3823                              <1> 	;	(internal clock/timer) functionality.
  3824                              <1> 	;	Then etc/init will enable clock/timer for
  3825                              <1> 	;	multi tasking. (Then it will not be disabled again
  3826                              <1> 	;	except hardware reset/restart.)
  3827                              <1> 
  3828 00003FF5 803D[F26E0000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3829                              <1> 	;;ja	error
  3830                              <1> 	;ja	badsys ; 14/05/2015
  3831                              <1> 	; 01/02/2022
  3832                              <1> 	;jna	short emt_0
  3833                              <1> 	;jmp	badsys
  3834 00003FFC 773A                <1> 	ja	short sysilgins ; jmp badsys
  3835                              <1> emt_0:
  3836 00003FFE FA                  <1> 	cli
  3837 00003FFF 21DB                <1> 	and	ebx, ebx
  3838 00004001 7429                <1> 	jz	short emt_2
  3839                              <1> 	; Enable multi tasking -time sharing-
  3840 00004003 B8[594F0000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3841                              <1> 	; 23/02/2022
  3842 00004008 BA[630A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3843                              <1> emt_1:
  3844 0000400D A3[29070000]        <1> 	mov	[x_timer], eax
  3845                              <1> 	; 23/02/2022 (Temporary)
  3846 00004012 8915[2D070000]      <1> 	mov	[x_rtci], edx
  3847 00004018 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3848 0000401A E853020000          <1> 	call	wttyc  ; clear video page
  3849 0000401F B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3850 00004021 E84C020000          <1> 	call	wttyc  ; clear video page
  3851                              <1> 	;
  3852 00004026 FB                  <1> 	sti
  3853 00004027 E9DAFAFFFF          <1> 	jmp	sysret
  3854                              <1> emt_2:
  3855                              <1> 	; Disable multi tasking -time sharing-
  3856 0000402C B8[35070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3857                              <1> 	; 23/02/2022
  3858 00004031 BA[6A0A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3859                              <1> 	;
  3860 00004036 EBD5                <1> 	jmp	short emt_1
  3861                              <1> 
  3862                              <1> 	; Original UNIX v1 'sysemt' routine
  3863                              <1> ;sysemt:
  3864                              <1>         ;
  3865                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3866                              <1> 			 ; / in loc 30
  3867                              <1>         ;cmp    30,$core / was the argument a lower address 
  3868                              <1> 			; / than core
  3869                              <1>         ;blo    1f / yes, rtssym
  3870                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3871                              <1> 			; / and less than "ecore"
  3872                              <1>         ;blo    2f / yes, sysret2
  3873                              <1> ;1:
  3874                              <1>         ;mov    $rtssym,30
  3875                              <1> ;2:
  3876                              <1>         ;br     sysret2
  3877                              <1> 
  3878                              <1> 	; 01/02/2022
  3879                              <1> sysilgins:
  3880                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3881                              <1> 	; 03/06/2013
  3882                              <1> 	; Retro UNIX 8086 v1 modification: 
  3883                              <1> 	;	not a valid system call ! (not in use)
  3884                              <1> 	;
  3885 00004038 E952FBFFFF          <1> 	jmp	badsys
  3886                              <1> 	;jmp	error
  3887                              <1> 	;;jmp 	sysret
  3888                              <1> 
  3889                              <1> 	; Original UNIX v1 'sysemt' routine
  3890                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3891                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3892                              <1> 			  ;/ put it in loc 8.,
  3893                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3894                              <1> 		       ; / trap address
  3895                              <1>         ;blo    1f / is the address a user core address?  
  3896                              <1> 		; / yes, go to 2f
  3897                              <1>         ;cmp    10,$ecore
  3898                              <1>         ;blo    2f
  3899                              <1> ;1:
  3900                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3901                              <1> 		    ; / instruction trap address for the system
  3902                              <1> ;2:
  3903                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3904                              <1> 
  3905                              <1> sysmdate: ; < change the modification time of a file >
  3906                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3907                              <1> 	;	(ECX input)
  3908                              <1> 	; 01/02/2022
  3909                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3910                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3911                              <1> 	;
  3912                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3913                              <1> 	; file into core. The user is checked if he is the owner 
  3914                              <1> 	; or super user. If he is neither an error occurs.
  3915                              <1> 	; 'setimod' is then called to set the i-node modification
  3916                              <1> 	; byte and the modification time, but the modification time
  3917                              <1> 	; is overwritten by whatever get put on the stack during
  3918                              <1> 	; a 'systime' system call. This calls are restricted to
  3919                              <1> 	; the super user.		
  3920                              <1> 	;
  3921                              <1> 	; Calling sequence:
  3922                              <1> 	;	sysmdate; name
  3923                              <1> 	; Arguments:
  3924                              <1> 	;	name - points to the name of file
  3925                              <1> 	; Inputs: (arguments)
  3926                              <1> 	; Outputs: -
  3927                              <1> 	; ...............................................................
  3928                              <1> 	;				
  3929                              <1> 	; Retro UNIX 8086 v1 modification: 
  3930                              <1> 	;	 The user/application program puts address 
  3931                              <1> 	;	 of the file name in BX register 
  3932                              <1> 	;	 as 'sysmdate' system call argument.
  3933                              <1> 	;
  3934                              <1> ; / change the modification time of a file
  3935                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3936 0000403D 891D[C46E0000]      <1>         mov	[u.namep], ebx
  3937                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3938 00004043 890D[306B0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3939 00004049 E88A090000          <1> 	call	namei
  3940                              <1> 		; jsr r0,namei / get its i-number
  3941                              <1> 	;;jc	error       
  3942                              <1> 		; br error2 / no, such file
  3943                              <1> 	;jc	fnotfound ; file not found !
  3944                              <1> 	; 01/02/2022
  3945 0000404E 7305                <1> 	jnc	short mdate_0
  3946 00004050 E9A0FEFFFF          <1> 	jmp	fnotfound
  3947                              <1> mdate_0:
  3948 00004055 E848110000          <1> 	call	iget
  3949                              <1> 		; jsr r0,iget / get i-node into core
  3950 0000405A A0[F26E0000]        <1> 	mov	al, [u.uid]
  3951 0000405F 3A05[AB6B0000]      <1> 	cmp	al, [i.uid]
  3952                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3953 00004065 7413                <1> 	je	short mdate_1
  3954                              <1>         	; beq 1f / yes
  3955 00004067 20C0                <1> 	and	al, al
  3956                              <1> 		; tstb u.uid / no, is user the super user
  3957                              <1> 	;jnz	error
  3958                              <1> 		; bne error2 / no, error
  3959 00004069 740F                <1> 	jz	short mdate_1
  3960 0000406B C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3960 00004073 0000                <1>
  3961                              <1> sysstty_err:	; 01/02/2022
  3962 00004075 E96CFAFFFF          <1> 	jmp	error
  3963                              <1> mdate_1: ;1:
  3964 0000407A E82D120000          <1> 	call	setimod
  3965                              <1>         	; jsr r0,setimod / fill in modification data,
  3966                              <1> 		               ; / time etc.
  3967 0000407F BE[306B0000]        <1> 	mov	esi, p_time
  3968 00004084 BF[C26B0000]        <1> 	mov	edi, i.mtim
  3969 00004089 A5                  <1> 	movsd
  3970                              <1> 		; mov 4(sp),i.mtim / move present time to
  3971                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3972 0000408A E977FAFFFF          <1>         jmp	sysret
  3973                              <1> 		; br sysret2
  3974                              <1> 
  3975                              <1> 	; 01/02/2022
  3976                              <1> sysstty_err_s:
  3977 0000408F 880D[AC6E0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3978 00004095 EBDE                <1> 	jmp	short sysstty_err
  3979                              <1> 
  3980                              <1> sysstty: ; < set tty status and mode >
  3981                              <1> 	; 23/02/2022
  3982                              <1> 	; 22/02/2022
  3983                              <1> 	; 02/02/2022
  3984                              <1> 	; 01/02/2022 (clear screen)
  3985                              <1> 	; 17/11/2015
  3986                              <1> 	; 12/11/2015
  3987                              <1> 	; 29/10/2015
  3988                              <1> 	; 17/10/2015
  3989                              <1> 	; 13/10/2015
  3990                              <1> 	; 29/06/2015
  3991                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3992                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3993                              <1> 	;
  3994                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3995                              <1> 	; whose file descriptor is in (u.r0).
  3996                              <1> 	;
  3997                              <1> 	; Calling sequence:
  3998                              <1> 	;	sysstty; arg
  3999                              <1> 	; Arguments:
  4000                              <1> 	;	arg - address of 3 consequitive words that contain
  4001                              <1> 	;	      the source of status data	
  4002                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4003                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4004                              <1> 	; ...............................................................
  4005                              <1> 	;	
  4006                              <1> 	; Retro UNIX 8086 v1 modification: 
  4007                              <1> 	;	'sysstty' system call will set the tty
  4008                              <1> 	;	(clear keyboard buffer and set cursor position)
  4009                              <1> 	;	 in following manner:
  4010                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4011                              <1> 	;
  4012                              <1> 	; Inputs:
  4013                              <1> 	;	BX = 0 --> means
  4014                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4015                              <1> 	;	      set cursor position for console tty, only 
  4016                              <1> 	;	      CH will be ignored (char. will not be written)	
  4017                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4018                              <1> 	;	      set console tty for (current) process
  4019                              <1> 	;	      CL = tty number (0 to 9)
  4020                              <1> 	;	      (If CH = 0, character will not be written)
  4021                              <1> 	;          If CH > 0 (CL < FFh)	
  4022                              <1> 	;             CL = tty number (0 to 9)
  4023                              <1> 	;	      CH = character will be written
  4024                              <1> 	;	        at requested cursor position (in DX)	
  4025                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4026                              <1>   	;		(only tty number 0 to 7) 
  4027                              <1> 	;          DL = communication parameters (for serial ports) 
  4028                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4029                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4030                              <1> 	;			or set cursor position	
  4031                              <1> 	;	   DH = 0FFh -> DL is not valid
  4032                              <1> 	;		do not set serial port parameters 
  4033                              <1> 	;		or do not set cursor position
  4034                              <1> 	;
  4035                              <1> 	;	BX > 0 --> points to name of tty
  4036                              <1> 	;    	   CH > 0 -->
  4037                              <1> 	;		CH = character will be written in current 
  4038                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4039                              <1> 	;	     	or character will be sent to serial port
  4040                              <1> 	;	     	(for tty number 8 or 9)
  4041                              <1> 	;		CL = color of the character if tty number < 8.
  4042                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4043                              <1> 	;		set mode (tty 8 to 9) or 
  4044                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4045                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4046                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4047                              <1> 	;		(DL is not valid)
  4048                              <1> 	;	   DL = communication parameters 
  4049                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4050                              <1> 	;
  4051                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4052                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4053                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4054                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4055                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4056                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4057                              <1> 	;
  4058                              <1> 	; Outputs:
  4059                              <1> 	;	cf = 0 -> OK
  4060                              <1> 	;	     AL = tty number (0 to 9)
  4061                              <1> 	;	     AH = line status if tty number is 8 or 9
  4062                              <1> 	;	     AH = process number (of the caller) 	
  4063                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4064                              <1> 	;	     AH = FFh if the tty is locked 
  4065                              <1> 	;		  (owned by another process)
  4066                              <1> 	;	        = process number (of the caller) 
  4067                              <1> 	;		  (if < FFh and tty number < 8)
  4068                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4069                              <1> 	;	     AH = line status if tty number is 8 or 9
  4070                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4071                              <1> 	;	
  4072                              <1> 
  4073                              <1> 	; 27/06/2015 (32 bit modifications)
  4074                              <1> 	; 14/01/2014
  4075 00004097 31C0                <1> 	xor 	eax, eax
  4076 00004099 6648                <1> 	dec	ax ; 17/10/2015
  4077 0000409B A3[AC6E0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4078                              <1> 	;;;
  4079                              <1> 	; 01/02/2022
  4080 000040A0 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4081 000040A2 39C2                <1> 	cmp	edx, eax
  4082                              <1> 	;cmp	dx, ax ; 0FFFFh
  4083 000040A4 7521                <1> 	jne	short sysstty_18
  4084                              <1> 	; clear video page
  4085                              <1> 	; (CH must be 0)
  4086 000040A6 08ED                <1> 	or	ch, ch
  4087 000040A8 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4088 000040AA 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4089 000040AD 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4090 000040AF 20C9                <1> 	and	cl, cl
  4091 000040B1 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4092 000040B3 0FB635[F56E0000]    <1> 	movzx	esi, byte [u.uno]
  4093 000040BA 8A8E[076C0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4094 000040C0 80F907              <1> 	cmp	cl, 7
  4095 000040C3 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4096                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4097 000040C5 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4098                              <1> sysstty_18:
  4099 000040C7 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4100                              <1> 	; cl = video page (tty) number		
  4101                              <1> 	;;;
  4102 000040C9 21DB                <1> 	and	ebx, ebx
  4103                              <1> 	;jnz	sysstty_6
  4104                              <1> 	; 01/02/2022
  4105 000040CB 7405                <1> 	jz	short sysstty_19
  4106 000040CD E9C2000000          <1> 	jmp	sysstty_6
  4107                              <1> sysstty_19:
  4108                              <1> 	; set console tty
  4109                              <1> 	; 29/10/2015
  4110                              <1> 	; 17/01/2014 
  4111 000040D2 80F909              <1> 	cmp	cl, 9
  4112 000040D5 7613                <1> 	jna	short sysstty_0
  4113                              <1> 	; 17/11/2015
  4114 000040D7 80F9FF              <1> 	cmp	cl, 0FFh
  4115 000040DA 7202                <1> 	jb	short sysstty_13
  4116 000040DC 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4117                              <1> sysstty_13:
  4118 000040DE 8A1D[F56E0000]      <1> 	mov	bl, [u.uno] ; process number
  4119 000040E4 8A8B[076C0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4120                              <1> sysstty_0:
  4121                              <1> 	; 29/06/2015
  4122                              <1> 	;push	dx
  4123                              <1> 	;push	cx
  4124                              <1> 	; 01/02/2022
  4125 000040EA 52                  <1> 	push	edx
  4126 000040EB 51                  <1> 	push	ecx
  4127 000040EC 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4128 000040EE 88C8                <1> 	mov	al, cl
  4129 000040F0 A2[AC6E0000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4130 000040F5 E8C6180000          <1> 	call	ottyp
  4131                              <1> 	; 01/02/2022
  4132 000040FA 59                  <1> 	pop	ecx
  4133 000040FB 5A                  <1> 	pop	edx
  4134                              <1> 	;pop	cx
  4135                              <1> 	;pop	dx
  4136                              <1> 	;
  4137 000040FC 7220                <1> 	jc	short sysstty_pd_err
  4138                              <1> 	;
  4139                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4140                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4141                              <1> 	;
  4142 000040FE 80F908              <1> 	cmp	cl, 8
  4143 00004101 720C                <1> 	jb	short sysstty_2
  4144                              <1> 	;
  4145 00004103 80FEFF              <1> 	cmp	dh, 0FFh
  4146 00004106 7407                <1> 	je	short sysstty_2
  4147                              <1> 		; set communication parameters for serial ports
  4148                              <1> 
  4149                              <1> ; 01/02/2022
  4150                              <1> ;	; 29/10/2015
  4151                              <1> ;	mov	ah, dl ; communication parameters
  4152                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4153                              <1> ;		;			 THRE int + RDA int 
  4154                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4155                              <1> ;		;			 THRE int + RDA int 
  4156                              <1> ;	sub	al, al ; 0
  4157                              <1> ;	; 12/07/2014
  4158                              <1> ;	cmp	cl, 9
  4159                              <1> ;	jb	short sysstty_1
  4160                              <1> ;	inc	al
  4161                              <1> ;sysstty_1:
  4162                              <1> ;	; 01/02/2022
  4163                              <1> ;	push	ecx
  4164                              <1> ;	;push	cx
  4165                              <1> ;	; 29/06/2015	
  4166                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4167                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4168                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4169                              <1> ;	; 01/02/2022
  4170                              <1> ;	pop	ecx	
  4171                              <1> ;	;pop	cx
  4172                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4173                              <1> 
  4174                              <1> 	; 01/02/2022
  4175 00004108 E832010000          <1> 	call	sysstty_scp
  4176 0000410D 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4177                              <1> 
  4178                              <1> sysstty_2:
  4179                              <1> 	; 17/01/2014
  4180 0000410F 20ED                <1> 	and	ch, ch 	; set cursor position 
  4181                              <1> 			; or comm. parameters ONLY
  4182 00004111 7527                <1> 	jnz	short sysstty_3
  4183                              <1> 	; 01/02/2022
  4184 00004113 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4185 00004117 7214                <1> 	jb	short sysstty_20
  4186                              <1> 	; clear screen (video page)
  4187 00004119 E93D010000          <1> 	jmp	sysstty_14
  4188                              <1> 
  4189                              <1> sysstty_pd_err: ; 29/06/2015
  4190                              <1> 	; 'permission denied !' error
  4191 0000411E C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4191 00004126 0000                <1>
  4192 00004128 E9B9F9FFFF          <1> 	jmp	error
  4193                              <1> 
  4194                              <1> sysstty_20:
  4195 0000412D 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4196 00004134 888B[076C0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4197                              <1> sysstty_3:
  4198                              <1> 	; 16/01/2014
  4199 0000413A 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4200                              <1> 	; 17/11/2015
  4201 0000413C B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4202 0000413E 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4203                              <1> 	;jna	sysstty_9
  4204                              <1> 	; 01/02/2022
  4205 00004140 7705                <1> 	ja	short sysstty_12
  4206 00004142 E9C7000000          <1> 	jmp	sysstty_9
  4207                              <1> 
  4208                              <1> sysstty_12:
  4209                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4210                              <1> 	; (Set specified serial port as console tty port)
  4211                              <1> 	; CH = character to be written
  4212                              <1> 	; 15/04/2014
  4213                              <1> 	; CH = 0 --> initialization only
  4214                              <1> 	; AL = character
  4215                              <1> 	; 26/06/2014
  4216 00004147 880D[FA6E0000]      <1> 	mov	[u.ttyn], cl
  4217                              <1> 	; 12/07/2014
  4218 0000414D 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4219                              <1> 	; 02/02/2022
  4220 0000414F FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4221 00004151 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4222 00004153 FEC8                <1> 	dec	al  ; 1 -> 0	
  4223                              <1> 	;and	al, al
  4224 00004155 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4225                              <1>  	; 04/07/2014
  4226 00004157 E8A01E0000          <1> 	call 	sndc
  4227                              <1> 	; 12/07/2014
  4228 0000415C EB0C                <1> 	jmp	short sysstty_5
  4229                              <1> 
  4230                              <1> sysstty_4:
  4231                              <1> 	; 12/07/2014
  4232                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4233 0000415E 88E0                <1> 	mov	al, ah ; 29/06/2015
  4234 00004160 2C08                <1> 	sub	al, 8
  4235                              <1> 	; 27/06/2015
  4236 00004162 E827F4FFFF          <1> 	call	sp_status ; get serial port status
  4237                              <1> 	; AL = Line status, AH = Modem status
  4238                              <1> 	; 12/11/2015
  4239 00004167 3C80                <1> 	cmp	al, 80h
  4240 00004169 F5                  <1> 	cmc
  4241                              <1> sysstty_5:
  4242 0000416A 66A3[AD6E0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4243                              <1> 		; EAX bits 16-23 = modem status	
  4244 00004170 9C                  <1> 	pushf
  4245 00004171 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4246 00004173 A0[FA6E0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4247 00004178 E866190000          <1> 	call	cttyp
  4248 0000417D 9D                  <1> 	popf
  4249                              <1> 	;jnc	sysret ; time out error 
  4250                              <1> 	; 01/02/2022
  4251 0000417E 7205                <1> 	jc	short sysstty_tmout_err
  4252 00004180 E981F9FFFF          <1> 	jmp	sysret
  4253                              <1> 
  4254                              <1> sysstty_tmout_err:
  4255 00004185 C705[FB6E0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4255 0000418D 0000                <1>
  4256 0000418F E952F9FFFF          <1> 	jmp	error
  4257                              <1> 
  4258                              <1> sysstty_6:
  4259                              <1> 	;push	dx
  4260                              <1> 	;push	cx
  4261                              <1> 	; 01/02/2022
  4262 00004194 52                  <1> 	push	edx
  4263 00004195 51                  <1> 	push	ecx
  4264 00004196 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  4265 0000419C E837080000          <1> 	call	namei
  4266                              <1> 	; 01/02/2022
  4267 000041A1 59                  <1> 	pop	ecx
  4268 000041A2 5A                  <1> 	pop	edx
  4269                              <1> 	;pop	cx
  4270                              <1> 	;pop	dx
  4271 000041A3 725A                <1> 	jc	short sysstty_inv_dn
  4272                              <1> 	;
  4273 000041A5 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4274 000041A9 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4275                              <1> 	;
  4276 000041AB 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4277                              <1> 		       ; /dev/COM1, /dev/COM2
  4278 000041AD 7206                <1> 	jb	short sysstty_7
  4279 000041AF 2C0A                <1> 	sub	al, 10
  4280                              <1> 	; al = 0 to 9
  4281 000041B1 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4282 000041B3 EB11                <1> 	jmp	short sysstty_8
  4283                              <1> 
  4284                              <1> sysstty_7:
  4285 000041B5 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4286 000041B7 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4287 000041B9 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4288 000041C0 8A83[076C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4289                              <1> sysstty_8:
  4290                              <1> 	; 22/02/2022
  4291                              <1> 	; (ebx < 256)
  4292 000041C6 A2[AC6E0000]        <1> 	mov	[u.r0], al
  4293                              <1> 	; 01/02/2022
  4294                              <1> 	;push	dx
  4295                              <1> 	;push	ax
  4296                              <1> 	;push	cx
  4297 000041CB 52                  <1> 	push	edx
  4298 000041CC 50                  <1> 	push	eax
  4299 000041CD 51                  <1> 	push	ecx
  4300 000041CE E8ED170000          <1> 	call	ottyp
  4301 000041D3 59                  <1> 	pop	ecx
  4302 000041D4 58                  <1> 	pop	eax
  4303 000041D5 5A                  <1> 	pop	edx
  4304                              <1> 	;pop	cx
  4305                              <1> 	;pop	ax
  4306                              <1> 	;pop	dx
  4307                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4308                              <1> 	; 01/02/2022
  4309 000041D6 7305                <1> 	jnc	short sysstty_21
  4310 000041D8 E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4311                              <1> sysstty_21:
  4312                              <1> 	; 29/10/2015
  4313 000041DD 86E9                <1> 	xchg 	ch, cl
  4314                              <1> 		; cl = character, ch = color code
  4315 000041DF 86C1                <1> 	xchg	al, cl
  4316                              <1> 		; al = character, cl = tty number
  4317 000041E1 80F907              <1> 	cmp	cl, 7
  4318                              <1> 	;ja	sysstty_12
  4319                              <1> 	; 01/02/2022
  4320 000041E4 7628                <1> 	jna	short sysstty_16
  4321                              <1> ;;
  4322 000041E6 80FEFF              <1> 	cmp	dh, 0FFh
  4323 000041E9 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4324                              <1> 
  4325                              <1> ; 01/02/2022
  4326                              <1> ;	; 29/10/2015
  4327                              <1> ;	mov	ah, dl ; communication parameters
  4328                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4329                              <1> ;		;			 THRE int + RDA int 
  4330                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4331                              <1> ;		;			 THRE int + RDA int 
  4332                              <1> ;	sub	al, al ; 0
  4333                              <1> ;	; 12/07/2014
  4334                              <1> ;	cmp	cl, 9
  4335                              <1> ;	jb	short sysstty_1
  4336                              <1> ;	inc	al
  4337                              <1> ;sysstty_1:
  4338                              <1> ;	; 01/02/2022
  4339                              <1> ;	push	ecx
  4340                              <1> ;	;push	cx
  4341                              <1> ;	; 29/06/2015	
  4342                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4343                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4344                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4345                              <1> ;	; 01/02/2022
  4346                              <1> ;	pop	ecx	
  4347                              <1> ;	;pop	cx
  4348                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4349                              <1> 
  4350                              <1> 	; 02/02/2022
  4351 000041EB 88C5                <1> 	mov	ch, al ; save char
  4352                              <1> 	; 01/02/2022
  4353 000041ED E84D000000          <1> 	call	sysstty_scp
  4354 000041F2 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4355                              <1> 	; 02/02/2022
  4356 000041F4 88E8                <1> 	mov	al, ch ; restore char
  4357                              <1> sysstty_22:
  4358                              <1> 	; 01/02/2022
  4359 000041F6 08ED                <1> 	or	ch, ch
  4360 000041F8 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4361                              <1> 	; send char to (serial port) terminal
  4362                              <1> 	; al = character
  4363                              <1> 	; cl = tty number (8 or 9)
  4364 000041FA E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4365                              <1> 
  4366                              <1> sysstty_inv_dn: 
  4367                              <1> 	; 27/06/2015
  4368                              <1> 	; Invalid device name (not a tty) ! error
  4369                              <1> 	; (Device is not a tty or device name not found)
  4370 000041FF C705[FB6E0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4370 00004207 0000                <1>
  4371 00004209 E9D8F8FFFF          <1> 	jmp	error 
  4372                              <1> 
  4373                              <1> sysstty_16:
  4374                              <1> 	; 22/02/2022
  4375                              <1> 	; 16/01/2014
  4376                              <1> 	;xor	bh, bh
  4377                              <1> sysstty_9: 	; tty 0 to tty 7
  4378                              <1> 	; al = character
  4379                              <1> 	; ch = color/attribute ; 01/02/2022
  4380                              <1> 	;
  4381                              <1>  	; 22/02/2022 (BugFix)
  4382                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4383 0000420E 29DB                <1> 	sub	ebx, ebx ; *
  4384 00004210 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4385                              <1> 	;
  4386 00004212 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4387 00004215 7409                <1> 	je	short sysstty_10
  4388                              <1> 	; 02/02/2022
  4389 00004217 51                  <1> 	push	ecx
  4390 00004218 50                  <1> 	push	eax
  4391                              <1> 	;push	cx
  4392                              <1> 	;push	ax	
  4393                              <1> 	; 22/02/2022	
  4394                              <1> 	;;movzx	ebx, cl ; *
  4395                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4396 00004219 E8CBD2FFFF          <1> 	call	set_cpos
  4397                              <1> 	;pop	ax
  4398                              <1> 	;pop	cx
  4399                              <1> 	; 02/02/2022
  4400 0000421E 58                  <1> 	pop	eax
  4401 0000421F 59                  <1> 	pop	ecx
  4402                              <1> sysstty_10: 
  4403                              <1> 	; 29/10/2015
  4404 00004220 08C0                <1> 	or	al, al ; character
  4405 00004222 740D                <1> 	jz      short sysstty_11 ; al = 0
  4406                              <1> 	; 17/11/2015
  4407 00004224 3CFF                <1> 	cmp	al, 0FFh
  4408 00004226 7309                <1> 	jnb	short sysstty_11
  4409                              <1> 		; ch > 0 and ch < FFh
  4410                              <1> 	; write a character at current cursor position
  4411 00004228 88EC                <1> 	mov	ah, ch ; color/attribute
  4412                              <1> 	; 12/07/2014
  4413                              <1> 	;push	cx
  4414                              <1> 	; 02/02/2022
  4415 0000422A 51                  <1> 	push	ecx
  4416 0000422B E8A5D3FFFF          <1> 	call	write_c_current
  4417                              <1> 	;pop	cx
  4418                              <1> 	; 02/02/2022
  4419 00004230 59                  <1> 	pop	ecx
  4420                              <1> sysstty_11:
  4421                              <1> 	; 14/01/2014
  4422 00004231 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4423                              <1> 	; 18/01/2014
  4424                              <1> 	;movzx	eax, cl ; 27/06/2015
  4425 00004233 88C8                <1> 	mov	al, cl
  4426 00004235 E8A9180000          <1> 	call	cttyp
  4427 0000423A E9C7F8FFFF          <1> 	jmp	sysret
  4428                              <1> 
  4429                              <1> sysstty_scp:
  4430                              <1> 	; 02/02/2022
  4431                              <1> 	; set communication parameters (for COM1 or COM2)
  4432                              <1> 	; 01/02/2022
  4433                              <1> 	;
  4434                              <1> 	; 29/10/2015
  4435 0000423F 88D4                <1> 	mov	ah, dl ; communication parameters
  4436                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4437                              <1> 		;			 THRE int + RDA int 
  4438                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4439                              <1> 		;			 THRE int + RDA int 
  4440 00004241 28C0                <1> 	sub	al, al ; 0
  4441                              <1> 	; 12/07/2014
  4442 00004243 80F909              <1> 	cmp	cl, 9
  4443 00004246 7202                <1> 	jb	short sysstty_1
  4444 00004248 FEC0                <1> 	inc	al
  4445                              <1> sysstty_1:
  4446                              <1> 	; 02/02/2022
  4447 0000424A 52                  <1> 	push	edx
  4448                              <1> 	; 01/02/2022
  4449 0000424B 51                  <1> 	push	ecx
  4450                              <1> 	;push	cx
  4451                              <1> 	; 29/06/2015	
  4452 0000424C E845F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4453 00004251 66890D[AD6E0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4454                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4455                              <1> 	; 01/02/2022
  4456 00004258 59                  <1> 	pop	ecx	
  4457                              <1> 	;pop	cx
  4458 00004259 5A                  <1> 	pop	edx ; 02/02/2022
  4459                              <1> 	; 01/02/2022
  4460                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4461 0000425A C3                  <1> 	retn
  4462                              <1> 
  4463                              <1> sysstty_14:
  4464                              <1> 	; 23/02/2022
  4465                              <1> 	; 02/02/2022
  4466                              <1> 	; ch = 0
  4467                              <1> 	; cl = video page
  4468                              <1> 	;
  4469                              <1> 	; dx = 0FFFFh
  4470                              <1> 	; clear screen (video page)
  4471                              <1> 	;
  4472                              <1> 
  4473                              <1> 	; 02/02/2022
  4474                              <1> 	; clear screen
  4475                              <1> 	;
  4476                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4477                              <1> 
  4478                              <1> 	; 23/02/2022
  4479 0000425B 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4480                              <1> 
  4481                              <1> 	; clear video page
  4482 0000425D E810000000          <1> 	call	wttyc ; 23/02/2022
  4483                              <1> 
  4484                              <1> 	; 23/02/2022
  4485 00004262 88D8                <1> 	mov	al, bl
  4486 00004264 8A25[F56E0000]      <1> 	mov	ah, [u.uno]
  4487 0000426A 66A3[AC6E0000]      <1> 	mov	[u.r0], ax
  4488 00004270 EBBF                <1> 	jmp	short sysstty_11
  4489                              <1> 
  4490                              <1> vp_clr:	; 27/02/2022
  4491                              <1> wttyc:
  4492                              <1> 	; 23/02/2022
  4493                              <1> 	; (clear video page)
  4494                              <1> 	; INPUT:
  4495                              <1> 	;  bl = video page (0 to 7)
  4496                              <1> 	;
  4497                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4498                              <1> 
  4499                              <1> 	;xor	dx, dx ; column 0, row 0
  4500                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4501                              <1> 	;
  4502                              <1> ;	movzx	ebx, cl
  4503                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4504                              <1> 
  4505                              <1> ;	shl 	bl, 1 
  4506                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4507                              <1> ;		; AL = lock value (0 or process number)
  4508                              <1> ;	or	al, al
  4509                              <1> ;	jz	short @f
  4510                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4511                              <1> ;	jne	short sysstty_15
  4512                              <1> ;		; only the owner can clear its video page
  4513                              <1> ;	xor	al, al ; 0
  4514                              <1> ;@@:
  4515                              <1> ;	;mov	bl, cl		
  4516                              <1> ;	shr	bl, 1 
  4517                              <1> 
  4518 00004272 30C0                <1> 	xor	al, al	; 0
  4519 00004274 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4520                              <1> 
  4521                              <1> 	; scroll_up input:
  4522                              <1> 	;
  4523                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4524                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4525                              <1> 	; ah = attribute to be used on blanked line
  4526                              <1> 	; bl = video page number (0 to 7)
  4527                              <1> 
  4528 00004276 E8F8D2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4529                              <1> 
  4530                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4531                              <1> 
  4532                              <1> 	; bl = video page number (0 to 7)
  4533                              <1> 	;xor	dx, dx ; column 0, row 0
  4534                              <1> 	; 02/02/2022
  4535 0000427B 31D2                <1> 	xor	edx, edx
  4536                              <1> 	; 23/02/2022
  4537                              <1> 	;call	set_cpos
  4538                              <1> 	;retn
  4539 0000427D E967D2FFFF          <1> 	jmp	set_cpos
  4540                              <1> 
  4541                              <1> 	;mov	al, bl
  4542                              <1> 	;mov	ah, [u.uno]
  4543                              <1> 	;mov	[u.r0], ax
  4544                              <1> 	;jmp	short sysstty_11
  4545                              <1> 
  4546                              <1> ;sysstty_15:
  4547                              <1> ;	; 30/01/2022
  4548                              <1> ;	; permission (denied) error
  4549                              <1> ;	;xor	dl, dl ; sysstty call sign
  4550                              <1> ;	mov	al, cl
  4551                              <1> ;	sub	ah, ah ; 0
  4552                              <1> ;	call	cttyp
  4553                              <1> ;	jmp	error
  4554                              <1> 
  4555                              <1> ; Original UNIX v1 'sysstty' routine:
  4556                              <1> ; gtty:
  4557                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4558                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4559                              <1> 	; 		/ r2 has source
  4560                              <1>         ;mov    r2,-(sp)
  4561                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4562                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4563                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4564                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4565                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4566                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4567                              <1>         ;       br .+4 / list empty, skip branch
  4568                              <1>         ;br     1b / get another character until list is empty
  4569                              <1>         ;mov    0b,r1 / move cc offset to r1
  4570                              <1>         ;inc    r1 / bump it for output clist
  4571                              <1>         ;tstb   cc(r1) / is it 0
  4572                              <1>         ;beq    1f / yes, no characters to output
  4573                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4574                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4575                              <1>         ;br     1b / try to calm it down again
  4576                              <1> ;1:
  4577                              <1>         ;mov    (sp)+,r1
  4578                              <1>         ;mov    (sp)+,r2 / restore registers
  4579                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4580                              <1>         ;beq    1f / if 0, 1f
  4581                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4582                              <1>         ;                   / control status register
  4583                              <1> ;1:
  4584                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4585                              <1>         ;beq    1f / if 0 1f
  4586                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4587                              <1> 	;		    / control status reg
  4588                              <1> ;1:
  4589                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4590                              <1>         ;jmp	sysret2 / return to user
  4591                              <1> 
  4592                              <1> sysgtty: ; < get tty status >
  4593                              <1> 	; 22/02/2022
  4594                              <1> 	; 01/02/2022
  4595                              <1> 	; 23/11/2015
  4596                              <1> 	; 29/10/2015
  4597                              <1> 	; 17/10/2015
  4598                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4599                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4600                              <1> 	;
  4601                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4602                              <1> 	; It stores in the three words addressed by it's argument
  4603                              <1> 	; the status of the typewriter whose file descriptor
  4604                              <1> 	; in (u.r0).
  4605                              <1> 	;
  4606                              <1> 	; Calling sequence:
  4607                              <1> 	;	sysgtty; arg
  4608                              <1> 	; Arguments:
  4609                              <1> 	;	arg - address of 3 words destination of the status
  4610                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4611                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4612                              <1> 	; ...............................................................
  4613                              <1> 	;	
  4614                              <1> 	; Retro UNIX 8086 v1 modification: 
  4615                              <1> 	;	'sysgtty' system call will return status of tty
  4616                              <1> 	;	(keyboard, serial port and video page status)
  4617                              <1> 	;	 in following manner:
  4618                              <1> 	;
  4619                              <1> 	; Inputs:
  4620                              <1> 	;	BX = 0 --> means 
  4621                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4622                              <1> 	;	                 for (current) process
  4623                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4624                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4625                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4626                              <1> 	;	     CH > 0 -->	tty number + 1
  4627                              <1> 	;
  4628                              <1> 	;	BX > 0 --> points to name of tty
  4629                              <1> 	;	     CL = 0 --> return keyboard status
  4630                              <1> 	;	     CL = 1 --> return video page status
  4631                              <1> 	;	     CH = undefined		 
  4632                              <1> 	;
  4633                              <1> 	; Outputs:
  4634                              <1> 	;	cf = 0 ->
  4635                              <1> 	;
  4636                              <1> 	;	     AL = tty number from 0 to 9
  4637                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4638                              <1> 	;	     AH = 0 if the tty is free/unused
  4639                              <1> 	;	     AH = the process number of the caller 
  4640                              <1>  	;	     AH = FFh if the tty is locked by another process
  4641                              <1> 	;
  4642                              <1> 	;	  (if calling is for serial port status)
  4643                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4644                              <1> 	;		  (BH = modem status, BL = Line status)
  4645                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4646                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4647                              <1> 	;
  4648                              <1> 	;	  (if calling is for keyboard status)
  4649                              <1> 	;	     BX = current character in tty/keyboard buffer
  4650                              <1> 	;		  (BH = scan code, BL = ascii code)
  4651                              <1> 	;		  (BX=0 if there is not a waiting character)
  4652                              <1> 	;	     CX  is undefined
  4653                              <1> 	;
  4654                              <1> 	;	  (if calling is for video page status)	
  4655                              <1> 	;	     BX = cursor position on the video page
  4656                              <1> 	;		  if tty number < 8
  4657                              <1> 	;		  (BH = row, BL = column)
  4658                              <1> 	;	     CX = current character (in cursor position)
  4659                              <1> 	;		  on the video page of the tty 
  4660                              <1> 	;		  if tty number < 8
  4661                              <1> 	;		  (CH = color, CL = character)
  4662                              <1> 	;	
  4663                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4664                              <1> 	;
  4665                              <1> 	;	     AH = FFh if the caller is not owner of
  4666                              <1> 	;		  specified tty or console tty
  4667                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4668                              <1> 	;	     BX, CX are undefined if cf = 1
  4669                              <1> 	;
  4670                              <1> 	;	  (If tty number is 8 or 9)
  4671                              <1> 	;	     AL = tty number 
  4672                              <1> 	;	     AH = the process number of the caller 
  4673                              <1> 	;	     BX = serial port status
  4674                              <1> 	;  		 (BH = modem status, BL = Line status)
  4675                              <1> 	;	     CX = 0
  4676                              <1> 	;
  4677                              <1> 		
  4678                              <1> gtty:   ; get (requested) tty number
  4679                              <1> 	; 22/02/2022
  4680                              <1> 	; 01/02/2022
  4681                              <1> 	; 17/10/2015
  4682                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4683                              <1> 	; 30/05/2013 - 12/07/2014
  4684                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4685                              <1> 	;
  4686                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4687                              <1> 	;
  4688                              <1> 	; 28/06/2015 (32 bit modifications)
  4689                              <1> 	; 16/01/2014
  4690 00004282 31C0                <1> 	xor 	eax, eax
  4691 00004284 6648                <1> 	dec	ax ; 17/10/2015
  4692 00004286 A3[AC6E0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4693 0000428B 80F901              <1> 	cmp	cl, 1
  4694 0000428E 760F                <1> 	jna	short sysgtty_0
  4695                              <1> sysgtty_invp:
  4696                              <1> 	; 28/06/2015
  4697 00004290 C705[FB6E0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4697 00004298 0000                <1>
  4698 0000429A E947F8FFFF          <1> 	jmp	error
  4699                              <1> sysgtty_0:	
  4700 0000429F 21DB                <1> 	and	ebx, ebx
  4701 000042A1 742E                <1> 	jz	short sysgtty_1
  4702                              <1> 	;
  4703 000042A3 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  4704                              <1> 	;push	cx ; 23/11/2015
  4705                              <1> 	; 01/02/2022
  4706 000042A9 51                  <1> 	push	ecx
  4707 000042AA E829070000          <1> 	call	namei
  4708                              <1> 	; 01/02/2022
  4709 000042AF 59                  <1> 	pop	ecx
  4710                              <1> 	;pop	cx ; 23/11/2015
  4711 000042B0 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4712                              <1> 	;
  4713 000042B2 6683F801            <1> 	cmp	ax, 1
  4714 000042B6 7622                <1> 	jna	short sysgtty_2
  4715                              <1> 	; 01/02/2022
  4716 000042B8 20E4                <1> 	and	ah, ah
  4717 000042BA 7506                <1> 	jnz	short sysgtty_inv_dn
  4718                              <1> 	;sub	ax, 10
  4719 000042BC 2C0A                <1> 	sub	al, 10
  4720 000042BE 3C09                <1> 	cmp	al, 9
  4721                              <1> 	;cmp	ax, 9
  4722                              <1> 	;ja	short sysgtty_inv_dn
  4723                              <1> 	;mov	ch, al
  4724                              <1> 	;jmp	short sysgtty_4
  4725                              <1> 	; 23/11/2015
  4726 000042C0 7629                <1> 	jna	short sysgtty_4
  4727                              <1> sysgtty_inv_dn: 
  4728                              <1> 	; 28/06/2015
  4729                              <1> 	; Invalid device name (not a tty) ! error
  4730                              <1> 	; (Device is not a tty or device name not found)
  4731 000042C2 C705[FB6E0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4731 000042CA 0000                <1>
  4732 000042CC E915F8FFFF          <1> 	jmp	error 
  4733                              <1> sysgtty_1:
  4734                              <1> 	; 16/01/2014
  4735 000042D1 80FD0A              <1> 	cmp	ch, 10
  4736 000042D4 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4737 000042D6 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4738 000042D8 790F                <1> 	jns	short sysgtty_3 ; not negative
  4739                              <1> 	;
  4740                              <1> sysgtty_2:
  4741                              <1> 	; get tty number of console tty
  4742 000042DA 8A25[F56E0000]      <1> 	mov	ah, [u.uno]
  4743                              <1>  	; 28/06/2015
  4744 000042E0 0FB6DC              <1> 	movzx 	ebx, ah
  4745 000042E3 8AAB[076C0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4746                              <1> sysgtty_3:
  4747 000042E9 88E8                <1> 	mov	al, ch
  4748                              <1> sysgtty_4:
  4749 000042EB A2[AC6E0000]        <1> 	mov	[u.r0], al
  4750                              <1>  	; 28/06/2015
  4751                              <1> 	;cmp	al, 9
  4752                              <1> 	;ja	short sysgtty_invp
  4753 000042F0 8B2D[A86E0000]      <1> 	mov	ebp, [u.usp]
  4754                              <1> 	; 23/11/2015
  4755 000042F6 20C9                <1> 	and	cl, cl
  4756 000042F8 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4757 000042FA 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4758 000042FC 722E                <1> 	jb	short sysgtty_6 ; video page status
  4759                              <1> 	; serial port status
  4760                              <1> 	; 12/07/2014
  4761                              <1> 	;mov	dx, 0
  4762                              <1> 	;je	short sysgtty_5
  4763                              <1> 	;inc	dl
  4764                              <1> ;sysgtty_5:
  4765                              <1> 	; 28/06/2015
  4766 000042FE 2C08                <1> 	sub	al, 8
  4767 00004300 E889F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4768                              <1> 	; AL = Line status, AH = Modem status
  4769 00004305 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4770 00004309 8A25[F56E0000]      <1> 	mov	ah, [u.uno]
  4771 0000430F 8825[AD6E0000]      <1>         mov     [u.r0+1], ah
  4772 00004315 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4773                              <1> 				; (in ECX)
  4774 0000431B A880                <1> 	test	al, 80h
  4775 0000431D 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4776 0000431F A801                <1> 	test	al, 1
  4777                              <1> 	;jz	sysret
  4778 00004321 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4779 00004323 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4780                              <1> sysgtty_10:
  4781 00004327 E9DAF7FFFF          <1> 	jmp	sysret
  4782                              <1> sysgtty_6:
  4783 0000432C A2[FA6E0000]        <1> 	mov	[u.ttyn], al ; tty number
  4784                              <1> 	;movzx	ebx, al
  4785 00004331 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4786 00004333 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4787                              <1> 	; 22/04/2014 - 29/06/2015
  4788 00004335 81C3[346B0000]      <1>         add     ebx, ttyl
  4789 0000433B 8A23                <1>  	mov	ah, [ebx]
  4790 0000433D 3A25[F56E0000]      <1> 	cmp	ah, [u.uno]
  4791 00004343 7404                <1> 	je	short sysgtty_7
  4792 00004345 20E4                <1> 	and	ah, ah
  4793                              <1> 	;jz	short sysgtty_7
  4794 00004347 7506                <1> 	jnz	short sysgtty_8
  4795                              <1> 	;mov	ah, 0FFh
  4796                              <1> sysgtty_7:
  4797 00004349 8825[AD6E0000]      <1>         mov     [u.r0+1], ah
  4798                              <1> sysgtty_8:
  4799 0000434F 08C9                <1> 	or	cl, cl
  4800 00004351 7510                <1> 	jnz	short sysgtty_9
  4801 00004353 B001                <1> 	mov	al, 1  ; test a key is available
  4802 00004355 E8251C0000          <1> 	call	getc
  4803 0000435A 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4804 0000435E E9A3F7FFFF          <1> 	jmp	sysret
  4805                              <1> sysgtty_9:
  4806 00004363 8A1D[FA6E0000]      <1> 	mov	bl, [u.ttyn]
  4807                              <1> 	; bl = video page number
  4808 00004369 E8821D0000          <1> 	call 	get_cpos
  4809                              <1> 	; dx = cursor position
  4810 0000436E 66895510            <1> 	mov	[ebp+16], dx ; bx
  4811                              <1> 	;mov	bl, [u.ttyn]
  4812                              <1> 	; bl = video page number
  4813 00004372 E88A1D0000          <1> 	call	read_ac_current
  4814                              <1> 	; ax = character and attribute/color
  4815 00004377 66894518            <1> 	mov	[ebp+24], ax ; cx
  4816 0000437B E986F7FFFF          <1> 	jmp	sysret
  4817                              <1> sysgtty_dnr_err:
  4818                              <1> 	; 'device not responding !' error	
  4819                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4820 00004380 C705[FB6E0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4820 00004388 0000                <1>
  4821 0000438A E957F7FFFF          <1> 	jmp	error	
  4822                              <1> 
  4823                              <1> ; Original UNIX v1 'sysgtty' routine:
  4824                              <1> ; sysgtty:
  4825                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4826                              <1> 	;	       / r2 has destination
  4827                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4828                              <1> 	;                     / in 1st word of dest
  4829                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4830                              <1> 	;                     / in 2nd word of dest
  4831                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4832                              <1>         ;jmp    sysret2 / return to user
  4833                              <1> 	
  4834                              <1> ; Original UNIX v1 'gtty' routine:
  4835                              <1> ; gtty:
  4836                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4837                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4838                              <1>         ;jsr    r0,getf / get the i-number of the file
  4839                              <1>         ;tst    r1 / is it open for reading
  4840                              <1>         ;bgt    1f / yes
  4841                              <1>         ;neg    r1 / no, i-number is negative, 
  4842                              <1> 	;          / so make it positive
  4843                              <1> ;1:
  4844                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4845                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4846                              <1>         ;bhis   error9 / no, error
  4847                              <1>         ;asl    r1 / 0%2
  4848                              <1>         ;asl    r1 / 0%4 / yes
  4849                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4850                              <1> 	;	       ; / tty block
  4851                              <1>         ;mov    u.off,r2 / put argument in r2
  4852                              <1>         ;rts    r0 / return
  2047                                  %include 'u2.s'        ; 11/05/2015
  2048                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC
  2049                              <1> ; Last Modification: 12/02/2022
  2050                              <1> ; ----------------------------------------------------------------------------
  2051                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2052                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2053                              <1> ;
  2054                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2055                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2056                              <1> ; <Bell Laboratories (17/3/1972)>
  2057                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2058                              <1> ;
  2059                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2060                              <1> ;
  2061                              <1> ; ****************************************************************************
  2062                              <1> ; 03/01/2016
  2063                              <1> 
  2064                              <1> syslink:
  2065                              <1> 	; 03/02/2022
  2066                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2067                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2068                              <1> 	;
  2069                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2070                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2071                              <1> 	; given to the entry that will go in the current directory.
  2072                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2073                              <1> 	; in the name 2 entry of current directory is the same
  2074                              <1> 	; i-number for the name 1 file.
  2075                              <1> 	;
  2076                              <1> 	; Calling sequence:
  2077                              <1> 	;	syslink; name 1; name 2
  2078                              <1> 	; Arguments:
  2079                              <1> 	;	name 1 - file name to which link will be created.
  2080                              <1> 	;	name 2 - name of entry in current directory that
  2081                              <1> 	;		 links to name 1.
  2082                              <1> 	; Inputs: -
  2083                              <1> 	; Outputs: -
  2084                              <1> 	; ...............................................................
  2085                              <1> 	;	
  2086                              <1> 	; Retro UNIX 8086 v1 modification: 
  2087                              <1> 	;       'syslink' system call has two arguments; so,
  2088                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2089                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2090                              <1> 	;
  2091                              <1> 		; / name1, name2
  2092                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2093 0000438F 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  2094 00004395 51                  <1> 	push	ecx
  2095 00004396 E83D060000          <1> 	call	namei
  2096                              <1> 		; jsr r0,namei / find the i-number associated with
  2097                              <1> 			     ; / the 1st path name
  2098                              <1>      	;;and	ax, ax
  2099                              <1> 	;;jz	error ; File not found
  2100                              <1> 	;jc	error 
  2101                              <1> 		; br error9 / cannot be found
  2102 0000439B 730F                <1> 	jnc	short syslink0
  2103                              <1> 	;pop 	ecx
  2104                              <1> 	; 'file not found !' error
  2105 0000439D C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2105 000043A5 0000                <1>
  2106 000043A7 E93AF7FFFF          <1> 	jmp	error
  2107                              <1> syslink0:
  2108 000043AC E8F10D0000          <1> 	call	iget
  2109                              <1> 		; jsr r0,iget / get the i-node into core
  2110 000043B1 8F05[C46E0000]      <1> 	pop	dword [u.namep] ; ecx
  2111                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2112                              <1> 	; 03/02/2022
  2113 000043B7 50                  <1> 	push	eax
  2114                              <1> 	;push	ax
  2115                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2116                              <1> 			    ; / (a link to this file is to be created)
  2117 000043B8 66FF35[906E0000]    <1> 	push	word [cdev]
  2118                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2119 000043BF E852000000          <1> 	call	isdir
  2120                              <1> 		; jsr r0,isdir / is it a directory
  2121 000043C4 E80F060000          <1> 	call	namei
  2122                              <1> 		; jsr r0,namei / no, get i-number of name2
  2123                              <1> 	;jnc	error
  2124                              <1> 		; br .+4   / not found 
  2125                              <1> 			 ; / so r1 = i-number of current directory
  2126                              <1> 			 ; / ii = i-number of current directory
  2127                              <1> 		; br error9 / file already exists., error
  2128 000043C9 720F                <1> 	jc	short syslink1
  2129                              <1> 	; pop ax
  2130                              <1> 	; pop ax
  2131                              <1> 	; 'file exists !' error
  2132 000043CB C705[FB6E0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2132 000043D3 0000                <1>
  2133 000043D5 E90CF7FFFF          <1> 	jmp	error
  2134                              <1> syslink1:
  2135 000043DA 6659                <1> 	pop	cx
  2136                              <1> 	;cmp	cx, [cdev]
  2137 000043DC 3A0D[906E0000]      <1> 	cmp	cl, [cdev]
  2138                              <1> 	;jne	error
  2139                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2140                              <1> 			       ; / end of current directory
  2141                              <1> 	        ; bne error9
  2142 000043E2 740F                <1> 	je	short syslink2
  2143                              <1> 	; 'not same drive !' error
  2144 000043E4 C705[FB6E0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2144 000043EC 0000                <1>
  2145 000043EE E9F3F6FFFF          <1> 	jmp	error
  2146                              <1> syslink2:
  2147                              <1> 	;pop	ax
  2148                              <1> 	;push	ax
  2149                              <1> 	; 03/02/2022
  2150                              <1> 	;mov	eax, [esp]
  2151 000043F3 58                  <1> 	pop	eax
  2152 000043F4 50                  <1> 	push	eax
  2153 000043F5 66A3[DE6E0000]      <1> 	mov	[u.dirbuf], ax
  2154                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2155 000043FB E89E000000          <1> 	call	mkdir
  2156                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2157                              <1> 		 	     ; / in current directory
  2158                              <1> 	; 03/02/2022
  2159 00004400 58                  <1> 	pop	eax
  2160                              <1> 	;pop	ax
  2161                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2162 00004401 E89C0D0000          <1> 	call	iget
  2163                              <1> 		; jsr r0,iget / get i-node into core
  2164 00004406 FE05[AA6B0000]      <1> 	inc	byte [i.nlks]
  2165                              <1> 		; incb i.nlks / add 1 to its number of links
  2166 0000440C E89B0E0000          <1> 	call	setimod
  2167                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2168 00004411 E9F0F6FFFF          <1> 	jmp	sysret
  2169                              <1> 
  2170                              <1> isdir:
  2171                              <1> 	; 03/02/2022
  2172                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2173                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2174                              <1> 	;
  2175                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2176                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2177                              <1> 	;  called by syslink and sysunlink to make sure directories
  2178                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2179                              <1> 	; 'isdir' does not bother checking. The current i-node
  2180                              <1> 	;  is not disturbed.			
  2181                              <1> 	;		
  2182                              <1> 	; INPUTS ->
  2183                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2184                              <1> 	;    u.uid - user id
  2185                              <1> 	; OUTPUTS ->
  2186                              <1> 	;    r1 - contains current i-number upon exit
  2187                              <1> 	;    	 (current i-node back in core) 
  2188                              <1> 	;	
  2189                              <1> 	; ((AX = R1))
  2190                              <1> 	;
  2191                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2192                              <1> 	;
  2193                              <1> 
  2194                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2195                              <1> 	; / there is an error unless super user made the call
  2196                              <1> 	
  2197 00004416 803D[F26E0000]00    <1> 	cmp	byte [u.uid], 0 
  2198                              <1> 		; tstb u.uid / super user
  2199 0000441D 762B                <1> 	jna	short isdir1
  2200                              <1> 		; beq 1f / yes, don't care
  2201 0000441F 66FF35[8C6E0000]    <1> 	push	word [ii]
  2202                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2203 00004426 E8770D0000          <1> 	call	iget
  2204                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2205                              <1> 	; 03/02/2022
  2206 0000442B F605[A96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2207                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2208                              <1> 		; bit $40000,i.flgs / is it a directory
  2209                              <1> 	;jnz	error
  2210                              <1> 		; bne error9 / yes, error
  2211 00004432 740F                <1> 	jz	short isdir0
  2212 00004434 C705[FB6E0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2212 0000443C 0000                <1>
  2213                              <1> 				; 'permission denied !' error
  2214                              <1> 	;pop	ax
  2215 0000443E E9A3F6FFFF          <1> 	jmp	error	
  2216                              <1> isdir0:	
  2217 00004443 6658                <1> 	pop	ax
  2218                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2219 00004445 E8580D0000          <1> 	call	iget
  2220                              <1> 		; jsr r0,iget / get it back in
  2221                              <1> isdir1: ; 1:
  2222 0000444A C3                  <1> 	retn
  2223                              <1> 		; rts r0
  2224                              <1> 
  2225                              <1> sysunlink:
  2226                              <1> 	; 03/02/2022
  2227                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2228                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2229                              <1> 	;
  2230                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2231                              <1> 	; name from its directory. If this entry was the last link
  2232                              <1> 	; to the file, the contents of the file are freed and the
  2233                              <1> 	; file is destroyed. If, however, the file was open in any
  2234                              <1> 	; process, the actual destruction is delayed until it is 
  2235                              <1> 	; closed, even though the directory entry has disappeared.
  2236                              <1> 	; 
  2237                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2238                              <1> 	; does not exist or that its directory can not be written.
  2239                              <1> 	; Write permission is not required on the file itself.
  2240                              <1> 	; It is also illegal to unlink a directory (except for
  2241                              <1> 	; the superuser).
  2242                              <1> 	;
  2243                              <1> 	; Calling sequence:
  2244                              <1> 	;	sysunlink; name
  2245                              <1> 	; Arguments:
  2246                              <1> 	;	name - name of directory entry to be removed 
  2247                              <1> 	; Inputs: -
  2248                              <1> 	; Outputs: -
  2249                              <1> 	; ...............................................................
  2250                              <1> 	;				
  2251                              <1> 	; Retro UNIX 8086 v1 modification:
  2252                              <1> 	;	 The user/application program puts address of the name
  2253                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2254                              <1> 
  2255                              <1> 	; / name - remove link name
  2256 0000444B 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  2257                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2258 00004451 E882050000          <1> 	call	namei
  2259                              <1> 		; jsr r0,namei / find the i-number associated 
  2260                              <1> 			     ; / with the path name
  2261                              <1> 	;jc	error
  2262                              <1> 		; br error9 / not found
  2263 00004456 730F                <1> 	jnc	short sysunlink1
  2264                              <1> 	; 'file not found !' error
  2265 00004458 C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2265 00004460 0000                <1>
  2266 00004462 E97FF6FFFF          <1> 	jmp	error
  2267                              <1> sysunlink1:
  2268                              <1> 	; 03/02/2022
  2269 00004467 50                  <1> 	push	eax
  2270                              <1> 	;push	ax
  2271                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2272 00004468 E8A9FFFFFF          <1> 	call	isdir
  2273                              <1> 		; jsr r0,isdir / is it a directory
  2274                              <1> 	;xor 	ax, ax
  2275                              <1> 	; 03/02/2022
  2276 0000446D 31C0                <1> 	xor	eax, eax
  2277 0000446F 66A3[DE6E0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2278                              <1> 		; clr u.dirbuf / no, clear the location that will
  2279                              <1> 			   ; / get written into the i-number portion
  2280                              <1> 			 ; / of the entry
  2281 00004475 832D[C86E0000]0A    <1> 	sub	dword [u.off], 10
  2282                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2283 0000447C E865000000          <1> 	call	wdir
  2284                              <1> 		; jsr r0,wdir / free the directory entry
  2285                              <1> 	; 03/02/2022
  2286 00004481 58                  <1> 	pop	eax
  2287                              <1> 	;pop	ax
  2288                              <1> 		; mov (sp)+,r1 / get i-number back
  2289 00004482 E81B0D0000          <1> 	call	iget
  2290                              <1> 		; jsr r0,iget / get i-node
  2291 00004487 E8200E0000          <1> 	call	setimod
  2292                              <1> 		; jsr r0,setimod / set modified flag
  2293 0000448C FE0D[AA6B0000]      <1> 	dec	byte [i.nlks]
  2294                              <1> 		; decb i.nlks / decrement the number of links
  2295                              <1> 	;jnz	sysret
  2296                              <1> 		; bgt sysret9 / if this was not the last link
  2297                              <1> 			    ; / to file return
  2298                              <1> 	; 03/02/2022
  2299 00004492 7505                <1> 	jnz	short sysunlink2
  2300                              <1> 	; AX = r1 = i-number
  2301 00004494 E860090000          <1> 	call	anyi
  2302                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2303                              <1> 			 ; / Then free contents of file and destroy it.
  2304                              <1> sysunlink2:
  2305 00004499 E968F6FFFF          <1> 	jmp	sysret
  2306                              <1> 		; br sysret9
  2307                              <1> 
  2308                              <1> mkdir:
  2309                              <1> 	; 03/02/2022
  2310                              <1> 	; 12/10/2015
  2311                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2312                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2313                              <1> 	;
  2314                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2315                              <1> 	; by u.namep into the current directory.
  2316                              <1> 	;
  2317                              <1> 	; INPUTS ->
  2318                              <1> 	;    u.namep - points to a file name 
  2319                              <1> 	;	           that is about to be a directory entry.
  2320                              <1> 	;    ii - current directory's i-number.	
  2321                              <1> 	; OUTPUTS ->
  2322                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2323                              <1> 	;    u.off - points to entry to be filled 
  2324                              <1> 	;	     in the current directory		
  2325                              <1> 	;    u.base - points to start of u.dirbuf.
  2326                              <1> 	;    r1 - contains i-number of current directory 
  2327                              <1> 	;	
  2328                              <1> 	; ((AX = R1)) output
  2329                              <1> 	;
  2330                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2331                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2332                              <1> 	;
  2333                              <1> 
  2334                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2335 0000449E 31C0                <1> 	xor 	eax, eax
  2336 000044A0 BF[E06E0000]        <1>         mov     edi, u.dirbuf+2
  2337 000044A5 89FE                <1> 	mov	esi, edi
  2338 000044A7 AB                  <1> 	stosd
  2339 000044A8 AB                  <1> 	stosd
  2340                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2341 000044A9 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2342                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2343                              <1> 	;mov 	ebp, [u.namep]
  2344 000044AB E864060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2345                              <1> 		; esi = physical address (page start + offset)
  2346                              <1> 		; ecx = byte count in the page (1 - 4096)
  2347                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2348                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2349                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2350                              <1> mkdir_1: ; 1: 
  2351 000044B0 45                  <1> 	inc	ebp ; 12/10/2015
  2352                              <1> 	;
  2353                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2354                              <1> 	 ; 01/08/2013
  2355 000044B1 AC                  <1> 	lodsb
  2356                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2357 000044B2 20C0                <1> 	and 	al, al
  2358 000044B4 7426                <1> 	jz 	short mkdir_3 	  
  2359                              <1> 		; beq 1f / if null, done
  2360 000044B6 3C2F                <1> 	cmp	al, '/'
  2361                              <1> 		; cmp r1,$'/ / is it a "/"?
  2362 000044B8 7413                <1> 	je	short mkdir_err
  2363                              <1> 	;je	error
  2364                              <1> 		; beq error9 / yes, error
  2365                              <1> 	; 03/02/2022
  2366 000044BA 49                  <1> 	dec	ecx
  2367                              <1> 	; 12/10/2015
  2368                              <1> 	;dec	cx
  2369 000044BB 7505                <1> 	jnz	short mkdir_2
  2370                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2371 000044BD E858060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2372                              <1> 		; esi = physical address (page start + offset)
  2373                              <1> 		; ecx = byte count in the page
  2374                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2375                              <1> mkdir_2:
  2376 000044C2 81FF[E86E0000]      <1> 	cmp     edi, u.dirbuf+10
  2377                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2378                              <1> 				     ; / a char?
  2379 000044C8 74E6                <1> 	je	short mkdir_1
  2380                              <1> 		; beq 1b / yes, go back
  2381 000044CA AA                  <1> 	stosb
  2382                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2383 000044CB EBE3                <1> 	jmp 	short mkdir_1
  2384                              <1> 		; br 1b / get next char
  2385                              <1> mkdir_err:
  2386                              <1> 	; 17/06/2015
  2387 000044CD C705[FB6E0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2387 000044D5 0000                <1>
  2388 000044D7 E90AF6FFFF          <1> 	jmp	error
  2389                              <1> mkdir_3: ; 1:
  2390 000044DC A1[C06E0000]        <1> 	mov	eax, [u.dirp]
  2391 000044E1 A3[C86E0000]        <1> 	mov	[u.off], eax
  2392                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2393                              <1> 				 ; / slot to u.off
  2394                              <1> wdir: 	; 03/02/2022
  2395                              <1> 	; 29/04/2013
  2396 000044E6 C705[CC6E0000]-     <1>         mov     dword [u.base], u.dirbuf
  2396 000044EC [DE6E0000]          <1>
  2397                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2398 000044F0 C705[D06E0000]0A00- <1>         mov     dword [u.count], 10
  2398 000044F8 0000                <1>
  2399                              <1> 		; mov $10.,u.count / u.count = 10
  2400 000044FA 66A1[8C6E0000]      <1> 	mov	ax, [ii] 
  2401                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2402 00004500 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2403 00004502 E86F0D0000          <1> 	call 	access
  2404                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2405                              <1> 				 ; / for writing
  2406                              <1> 	; AX = i-number of current directory
  2407                              <1> 	; 01/08/2013
  2408 00004507 FE05[0D6F0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2409                              <1> 	;call	writei
  2410                              <1> 	;	; jsr r0,writei / write into directory
  2411                              <1> 	;retn	
  2412                              <1> 	;	; rts r0
  2413                              <1> 	; 03/02/2022
  2414 0000450D E952100000          <1> 	jmp	writei
  2415                              <1> 
  2416                              <1> sysexec:
  2417                              <1> 	; 03/02/2022
  2418                              <1> 	; 23/10/2015
  2419                              <1> 	; 19/10/2015
  2420                              <1> 	; 10/10/2015, 18/10/2015
  2421                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2422                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2423                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2424                              <1> 	; 24/06/2015, 25/06/2015
  2425                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2426                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2427                              <1> 	;
  2428                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2429                              <1> 	; pointed to by 'name' in the sysexec call. 
  2430                              <1> 	; 'sysexec' performs the following operations:
  2431                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2432                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2433                              <1> 	;    3. sets trap vectors to system routines.
  2434                              <1> 	;    4. loads arguments to be passed to executing file into
  2435                              <1> 	;	highest locations of user's core
  2436                              <1> 	;    5. puts pointers to arguments in locations immediately
  2437                              <1> 	;	following arguments.
  2438                              <1> 	;    6.	saves number of arguments in next location.
  2439                              <1> 	;    7. intializes user's stack area so that all registers
  2440                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2441                              <1> 	;	to core when 'sysret' restores registers 
  2442                              <1> 	;	and does an rti.
  2443                              <1> 	;    8. inializes u.r0 and u.sp
  2444                              <1> 	;    9. zeros user's core down to u.r0
  2445                              <1> 	;   10.	reads executable file from storage device into core
  2446                              <1> 	;	starting at location 'core'.
  2447                              <1> 	;   11.	sets u.break to point to end of user's code with
  2448                              <1> 	;	data area appended.
  2449                              <1> 	;   12.	calls 'sysret' which returns control at location
  2450                              <1> 	;	'core' via 'rti' instruction. 		  		
  2451                              <1> 	;
  2452                              <1> 	; Calling sequence:
  2453                              <1> 	;	sysexec; namep; argp
  2454                              <1> 	; Arguments:
  2455                              <1> 	;	namep - points to pathname of file to be executed
  2456                              <1> 	;	argp  - address of table of argument pointers
  2457                              <1> 	;	argp1... argpn - table of argument pointers
  2458                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2459                              <1> 	; Inputs: (arguments)
  2460                              <1> 	; Outputs: -	
  2461                              <1> 	; ...............................................................
  2462                              <1> 	;
  2463                              <1> 	; Retro UNIX 386 v1 modification: 
  2464                              <1> 	;	User application runs in it's own virtual space 
  2465                              <1> 	;	which is izolated from kernel memory (and other
  2466                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2467                              <1> 	;	privilige mode. Virtual start address is always 0.
  2468                              <1> 	;	User's core memory starts at linear address 400000h
  2469                              <1> 	;	(the end of the 1st 4MB).
  2470                              <1> 	;
  2471                              <1> 	; Retro UNIX 8086 v1 modification: 
  2472                              <1> 	;	user/application segment and system/kernel segment
  2473                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2474                              <1> 	;	are different (user's registers are saved to 
  2475                              <1> 	;	and then restored from system's stack.)
  2476                              <1> 	;
  2477                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2478                              <1> 	;	      arguments which were in these registers;
  2479                              <1> 	;	      but, it returns by putting the 1st argument
  2480                              <1> 	;	      in 'u.namep' and the 2nd argument
  2481                              <1> 	;	      on top of stack. (1st argument is offset of the
  2482                              <1> 	;	      file/path name in the user's program segment.)		 	
  2483                              <1> 	
  2484                              <1> 	;call	arg2
  2485                              <1> 	; * name - 'u.namep' points to address of file/path name
  2486                              <1> 	;          in the user's program segment ('u.segmnt')
  2487                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2488                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2489                              <1> 	;          which is on top of stack.
  2490                              <1> 	;
  2491                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2492                              <1> 
  2493                              <1> 	; 23/06/2015 (32 bit modifications)
  2494                              <1> 
  2495 00004512 891D[C46E0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2496                              <1>         ; 18/10/2015
  2497 00004518 890D[246F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2498 0000451E E8B5040000          <1> 	call	namei
  2499                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2500                              <1> 			     ; / named in sysexec call in r1
  2501                              <1> 	;jc	error
  2502                              <1> 		; br error9
  2503 00004523 731E                <1> 	jnc	short sysexec_0
  2504                              <1> 	;
  2505                              <1> 	; 'file not found !' error
  2506 00004525 C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2506 0000452D 0000                <1>
  2507 0000452F E9B2F5FFFF          <1> 	jmp	error 
  2508                              <1> sysexec_not_exf:
  2509                              <1> 	; 'not executable file !' error
  2510 00004534 C705[FB6E0000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2510 0000453C 0000                <1>
  2511 0000453E E9A3F5FFFF          <1> 	jmp	error 
  2512                              <1> sysexec_0:
  2513 00004543 E85A0C0000          <1> 	call	iget
  2514                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2515                              <1> 	; 03/02/2022
  2516 00004548 F605[A86B0000]10    <1> 	test	byte [i.flgs], 10h
  2517                              <1>         ;test	word [i.flgs], 10h
  2518                              <1> 		; bit $20,i.flgs / is file executable
  2519 0000454F 74E3                <1> 	jz	short sysexec_not_exf
  2520                              <1> 	;jz	error
  2521                              <1> 		; beq error9
  2522                              <1> 	;;
  2523 00004551 E8D0130000          <1> 	call	iopen
  2524                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2525                              <1> 			     ; / given in r1 (opens file)
  2526                              <1> 	; AX = i-number of the file
  2527                              <1> 	; 03/02/2022
  2528 00004556 F605[A86B0000]20    <1> 	test	byte [i.flgs], 20h
  2529                              <1> 	;test	word [i.flgs], 20h
  2530                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2531 0000455D 7415                <1> 	jz	short sysexec_1
  2532                              <1> 		; beq 1f
  2533 0000455F 803D[F26E0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2534                              <1> 		; tstb u.uid / test user id
  2535 00004566 760C                <1> 	jna	short sysexec_1
  2536                              <1> 		; beq 1f / super user
  2537 00004568 8A0D[AB6B0000]      <1> 	mov	cl, [i.uid]
  2538 0000456E 880D[F26E0000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2539                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2540                              <1> 				 ; / as process user id
  2541                              <1> sysexec_1:
  2542                              <1> 	; 03/02/2022
  2543                              <1> 	; 18/10/2215
  2544                              <1> 	; 10/10/2015
  2545                              <1> 	; 21/07/2015, 24/07/2015
  2546                              <1> 	; 24/06/2015, 25/06/2015
  2547                              <1>         ; Moving arguments to the end of [u.upage]
  2548                              <1> 	; (by regarding page borders in user's memory space)
  2549                              <1> 	;
  2550                              <1> 	; 10/10/2015
  2551                              <1> 	; 21/07/2015
  2552 00004574 89E5                <1> 	mov	ebp, esp ; (**)
  2553                              <1> 	; 18/10/2015
  2554 00004576 89EF                <1> 	mov 	edi, ebp
  2555 00004578 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2556                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2557 0000457D 29CF                <1> 	sub	edi, ecx
  2558 0000457F 89FC                <1> 	mov	esp, edi
  2559 00004581 31C0                <1> 	xor	eax, eax
  2560 00004583 A3[D46E0000]        <1> 	mov 	[u.nread], eax ; 0
  2561                              <1> 	; 03/02/2022
  2562                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2563                              <1> 	; may leave it with any value after an error))
  2564                              <1> 	;mov	[argc], ax
  2565 00004588 A2[226F0000]        <1> 	mov	[argc], al ; 0
  2566                              <1> 	;
  2567 0000458D 49                  <1> 	dec	ecx ; 256 - 1
  2568 0000458E 890D[D06E0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2569                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2570                              <1> sysexec_2:
  2571 00004594 8B35[246F0000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2572 0000459A E861020000          <1> 	call	get_argp
  2573                              <1> 	;mov	ecx, 4 
  2574                              <1> 	; 03/02/2022
  2575 0000459F 31C9                <1> 	xor	ecx, ecx
  2576 000045A1 B104                <1> 	mov	cl, 4
  2577                              <1> sysexec_3:
  2578 000045A3 21C0                <1> 	and	eax, eax
  2579 000045A5 7456                <1> 	jz	short sysexec_6
  2580                              <1> 	; 18/10/2015
  2581 000045A7 010D[246F0000]      <1> 	add	[argv], ecx ; 4
  2582 000045AD 66FF05[226F0000]    <1> 	inc	word [argc]
  2583                              <1> 	;
  2584 000045B4 A3[CC6E0000]        <1> 	mov	[u.base], eax
  2585                              <1>  	; 23/10/2015
  2586 000045B9 66C705[0B6F0000]00- <1> 	mov	word [u.pcount], 0
  2586 000045C1 00                  <1>
  2587                              <1> sysexec_4:
  2588 000045C2 E852110000          <1> 	call	cpass ; get a character from user's core memory
  2589 000045C7 750B                <1>         jnz	short sysexec_5
  2590                              <1> 		; (max. 255 chars + null)
  2591                              <1> 	; 18/10/2015
  2592 000045C9 28C0                <1> 	sub 	al, al
  2593 000045CB AA                  <1> 	stosb
  2594 000045CC FF05[D46E0000]      <1> 	inc	dword [u.nread]
  2595 000045D2 EB29                <1> 	jmp	short sysexec_6
  2596                              <1> sysexec_5:
  2597 000045D4 AA                  <1> 	stosb
  2598 000045D5 20C0                <1> 	and 	al, al
  2599 000045D7 75E9                <1> 	jnz	short sysexec_4
  2600                              <1> 	;mov	ecx, 4
  2601                              <1> 	; 03/02/2022
  2602 000045D9 29C9                <1> 	sub	ecx, ecx
  2603 000045DB B104                <1> 	mov	cl, 4
  2604                              <1> 	;cmp	[ncount], ecx ; 4
  2605                              <1> 	; 03/02/2022
  2606 000045DD 66390D[206F0000]    <1> 	cmp	[ncount], cx ; 4
  2607 000045E4 72AE                <1> 	jb	short sysexec_2
  2608 000045E6 8B35[1C6F0000]      <1> 	mov	esi, [nbase]
  2609 000045EC 010D[1C6F0000]      <1> 	add	[nbase], ecx ; 4	
  2610 000045F2 66290D[206F0000]    <1> 	sub	[ncount], cx 
  2611 000045F9 8B06                <1> 	mov	eax, [esi]
  2612 000045FB EBA6                <1> 	jmp	short sysexec_3
  2613                              <1> sysexec_6:
  2614                              <1> 	; 18/10/2015
  2615                              <1> 	; argument list transfer from user's core memory to
  2616                              <1> 	; kernel stack frame is OK here.
  2617                              <1> 	; [u.nread] = ; argument list length
  2618                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2619                              <1> 	;
  2620                              <1> 	; 18/10/2015
  2621                              <1>         ; 21/07/2015, 24/07/2015
  2622                              <1> 	; 25/06/2015, 02/07/2015
  2623                              <1> 	; 23/06/2015, 24/06/2015
  2624                              <1> 	;
  2625 000045FD 8B1D[036F0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2626 00004603 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2627 00004605 740A                <1> 	jz	short sysexec_7
  2628 00004607 A1[FF6E0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2629 0000460C E8F3E8FFFF          <1> 	call	deallocate_page_dir
  2630                              <1> sysexec_7:
  2631 00004611 E823E8FFFF          <1> 	call	make_page_dir
  2632                              <1> 	;jc	short sysexec_14
  2633                              <1> 	;jc	panic  ; allocation error 
  2634                              <1> 		       ; after a deallocation would be nonsence !?
  2635                              <1> 	; 03/02/2022
  2636 00004616 7243                <1> 	jc	short sysexec_panic
  2637                              <1> 
  2638                              <1> 	; 24/07/2015
  2639                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2640                              <1> 	;     of the user's page directory
  2641                              <1> 	;     (It is needed for interrupts!)
  2642                              <1> 	; 18/10/2015
  2643 00004618 8B15[E86A0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2644 0000461E 8B02                <1> 	mov	eax, [edx] ; physical address of
  2645                              <1> 			   ; kernel's first page table (1st 4 MB)
  2646                              <1> 			   ; (PDE 0 of kernel's page directory)
  2647 00004620 8B15[FF6E0000]      <1> 	mov 	edx, [u.pgdir]
  2648 00004626 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2649                              <1> 	;
  2650                              <1> 	; 20/07/2015
  2651 00004628 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2652                              <1> 	; 18/10/2015
  2653 0000462D BE[146F0000]        <1> 	mov	esi, pcore ; physical start address
  2654                              <1> sysexec_8:	
  2655 00004632 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2656 00004637 E81BE8FFFF          <1> 	call	make_page_table
  2657                              <1> 	;jc	panic
  2658                              <1> 	; 03/02/2022
  2659 0000463C 721D                <1> 	jc	short sysexec_panic
  2660                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2661 0000463E E822E8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2662                              <1> 	;jc	panic
  2663                              <1> 	; 03/02/2022
  2664 00004643 7216                <1> 	jc	short sysexec_panic
  2665                              <1> 	;
  2666 00004645 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2667                              <1> 	; ebx = virtual address (24/07/2015)
  2668                              <1> 	; 03/02/2022
  2669                              <1> 	;call 	add_to_swap_queue
  2670                              <1> 	; 18/10/2015
  2671 00004647 81FE[186F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2672 0000464D 7411                <1> 	je	short sysexec_9 ; yes
  2673 0000464F BE[186F0000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2674                              <1> 	; 20/07/2015
  2675 00004654 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2676                              <1> 	; ebx = virtual end address + segment base address - 4K
  2677 00004659 EBD7                <1>         jmp     short sysexec_8
  2678                              <1> 
  2679                              <1> sysexec_panic:
  2680                              <1> 	; 03/02/2022
  2681 0000465B E93AEDFFFF          <1> 	jmp	panic
  2682                              <1> 
  2683                              <1> sysexec_9:
  2684                              <1> 	; 18/10/2015
  2685                              <1> 	; 26/08/2015
  2686                              <1> 	; 25/06/2015
  2687                              <1> 	; move arguments from kernel stack to [ecore]
  2688                              <1> 	; (argument list/line will be copied from kernel stack
  2689                              <1> 	; frame to the last (stack) page of user's core memory)
  2690                              <1> 	; 18/10/2015
  2691 00004660 8B3D[186F0000]      <1> 	mov	edi, [ecore]
  2692 00004666 81C700100000        <1> 	add	edi, PAGE_SIZE
  2693                              <1> 	;movzx	eax, word [argc]
  2694                              <1> 	; 03/02/2022
  2695 0000466C 31C0                <1> 	xor	eax, eax
  2696 0000466E A0[226F0000]        <1> 	mov	al, [argc]
  2697 00004673 08C0                <1> 	or	al, al
  2698                              <1> 	;or	eax, eax
  2699 00004675 7509                <1> 	jnz	short sysexec_10
  2700 00004677 89FB                <1> 	mov 	ebx, edi
  2701 00004679 83EB04              <1> 	sub	ebx, 4 
  2702 0000467C 8903                <1> 	mov	[ebx], eax ; 0
  2703 0000467E EB40                <1> 	jmp 	short sysexec_13
  2704                              <1> sysexec_10:
  2705 00004680 8B0D[D46E0000]      <1> 	mov	ecx, [u.nread]
  2706                              <1> 	;mov 	esi, [argv}
  2707 00004686 89E6                <1> 	mov	esi, esp ; start address of argument list
  2708 00004688 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2709 0000468A 89C2                <1> 	mov	edx, eax
  2710                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2711 0000468C FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2712 0000468E C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2713                              <1> 	; edx <= 128
  2714 00004691 89FB                <1> 	mov	ebx, edi
  2715 00004693 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2716 00004696 29D3                <1> 	sub 	ebx, edx
  2717 00004698 89FA                <1> 	mov	edx, edi
  2718 0000469A F3A4                <1> 	rep	movsb
  2719 0000469C 89D6                <1> 	mov 	esi, edx
  2720 0000469E 89DF                <1> 	mov 	edi, ebx
  2721 000046A0 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2722 000046A5 2B15[186F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2723 000046AB AB                  <1> 	stosd	; eax = argument count	
  2724                              <1> sysexec_11:
  2725 000046AC 89F0                <1> 	mov	eax, esi
  2726 000046AE 01D0                <1> 	add	eax, edx
  2727 000046B0 AB                  <1> 	stosd  ; eax = virtual address
  2728 000046B1 FE0D[226F0000]      <1> 	dec	byte [argc]
  2729 000046B7 7407                <1> 	jz	short sysexec_13
  2730                              <1> sysexec_12:
  2731 000046B9 AC                  <1> 	lodsb
  2732 000046BA 20C0                <1> 	and	al, al
  2733 000046BC 75FB                <1> 	jnz	short sysexec_12
  2734 000046BE EBEC                <1> 	jmp	short sysexec_11
  2735                              <1> 	;
  2736                              <1> 	; 1:
  2737                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2738                              <1> 			     ; / pointers to arguments to be passed
  2739                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2740                              <1> 			      ; / u.quit = 1 take quit
  2741                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2742                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2743                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2744                              <1> 			       ; / system routine
  2745                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2746                              <1> 			       ; / set to take system routine
  2747                              <1> 		; mov $sstack,sp / stack space used during swapping
  2748                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2749                              <1> 		; mov $ecore,r5 / r5 has end of core
  2750                              <1> 		; mov $core,r4 / r4 has start of users core
  2751                              <1> 		; mov r4,u.base / u.base has start of users core
  2752                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2753                              <1> 	; 1:
  2754                              <1> 		; tst (r2)+ / argument char = "nul"
  2755                              <1> 		; bne 1b
  2756                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2757                              <1> 			  ; / end of argument pointer list
  2758                              <1> 	; 1:
  2759                              <1> 	     ; / move arguments to bottom of users core
  2760                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2761                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2762                              <1> 			    ; / ptr list
  2763                              <1> 		; blo 1f / branch to 1f when all arguments
  2764                              <1> 		       ; / are moved
  2765                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2766                              <1> 	; 2:
  2767                              <1> 		; tstb (r3)+
  2768                              <1> 		; bne 2b / scan argument for \0 (nul)
  2769                              <1> 
  2770                              <1> 	; 2:
  2771                              <1> 		; movb -(r3),-(r5) / move argument char 
  2772                              <1> 				 ; / by char starting at "ecore"
  2773                              <1> 		; cmp r3,(r2) / moved all characters in 
  2774                              <1> 			    ; / this argument
  2775                              <1> 		; bhi 2b / branch 2b if not
  2776                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2777                              <1> 			     ; / r5 has pointer to nth arg
  2778                              <1> 		; br 1b / string
  2779                              <1> 	; 1:
  2780                              <1> 		; clrb -(r5)
  2781                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2782                              <1> 			 ; / last word of argument strings
  2783                              <1> 		; mov $core,r2
  2784                              <1> 	
  2785                              <1> 	; 1: / move argument pointers into core following 
  2786                              <1> 	      ; / argument strings
  2787                              <1> 		; cmp r2,r4
  2788                              <1> 		; bhis 1f / branch to 1f when all pointers
  2789                              <1> 			; / are moved
  2790                              <1> 		; mov (r2)+,-(r5)
  2791                              <1> 		; br 1b
  2792                              <1> 	; 1:
  2793                              <1> 		; sub $core,r4 / gives number of arguments *2
  2794                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2795                              <1> 		       ; / the number of args stored
  2796                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2797                              <1> 			     ; / of the argument pointers
  2798                              <1> sysexec_13:
  2799                              <1> 	; 19/10/2015
  2800                              <1> 	; 18/10/2015
  2801                              <1> 	; 29/07/2015
  2802                              <1> 	; 24/07/2015, 25/07/2015
  2803                              <1> 	; 25/06/2015, 20/07/2015
  2804                              <1> 	; 23/06/2015, 24/06/2015
  2805                              <1> 	;
  2806                              <1> 	; moving arguments to [ecore] is OK here..
  2807                              <1> 	; 18/10/2015
  2808 000046C0 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2809                              <1> 	; ebx = beginning addres of argument list pointers
  2810                              <1> 	;	in user's stack
  2811                              <1> 	; 19/10/2015
  2812 000046C2 2B1D[186F0000]      <1> 	sub 	ebx, [ecore]
  2813 000046C8 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2814                              <1> 			; end of core - 4096 (last page)
  2815                              <1> 			; (virtual address)
  2816 000046CE 891D[246F0000]      <1> 	mov	[argv], ebx
  2817 000046D4 891D[D86E0000]      <1> 	mov	[u.break], ebx ; available user memory
  2818                              <1> 	;
  2819 000046DA 29C0                <1> 	sub	eax, eax
  2820 000046DC C705[D06E0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2820 000046E4 0000                <1>
  2821                              <1> 		; mov $14,u.count
  2822 000046E6 C705[BC6E0000]-     <1> 	mov	dword [u.fofp], u.off
  2822 000046EC [C86E0000]          <1>
  2823                              <1> 		; mov $u.off,u.fofp
  2824 000046F0 A3[C86E0000]        <1> 	mov	[u.off], eax ; 0
  2825                              <1> 		; clr u.off / set offset in file to be read to zero
  2826                              <1> 	; 25/07/2015
  2827 000046F5 A3[CC6E0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2828                              <1> 	; 25/06/2015 
  2829 000046FA 66A1[8C6E0000]      <1> 	mov	ax, [ii]
  2830                              <1> 	; AX = i-number of the executable file
  2831 00004700 E8710C0000          <1> 	call	readi
  2832                              <1> 		; jsr r0,readi / read in first six words of 
  2833                              <1> 			; / user's file, starting at $core
  2834                              <1> 		; mov sp,r5 / put users stack address in r5
  2835                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2836                              <1> 				; / from r5 (leaves number of words
  2837                              <1> 				; / less 26 available for
  2838                              <1> 			     	; / program in user core
  2839                              <1> 		; mov r5,u.count /
  2840                              <1> 	; 25/06/2015
  2841 00004705 8B0D[D86E0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2842 0000470B 890D[D06E0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2843                              <1> 	;
  2844 00004711 8B0D[D46E0000]      <1> 	mov	ecx, [u.nread]
  2845 00004717 890D[D86E0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2846 0000471D 80F920              <1> 	cmp	cl, 32
  2847 00004720 7540                <1>         jne     short sysexec_15
  2848                              <1> 	;:
  2849                              <1> 	; 25/06/2015
  2850                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2851                              <1> 	; 18/10/2015
  2852 00004722 8B35[146F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2853                              <1> 		             ; (phys. start addr. of the exec. file)
  2854 00004728 AD                  <1> 	lodsd
  2855 00004729 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2856 0000472D 7533                <1> 	jne	short sysexec_15
  2857                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2858                              <1> 			      ; / if file is standard a.out format
  2859                              <1> 		; bne 1f / branch, if not standard format
  2860 0000472F AD                  <1> 	lodsd
  2861 00004730 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2862 00004732 AD                  <1> 	lodsd
  2863 00004733 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2864                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2865                              <1> 		              ; / number of bytes in program text	
  2866                              <1> 		; sub $14,r5 / subtract 12
  2867 00004735 89CB                <1> 	mov	ebx, ecx
  2868                              <1> 	;
  2869                              <1> 	; 25/06/2015
  2870                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2871                              <1> 	;	and SINGLIX operating systems (as code template).
  2872                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2873                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2874                              <1> 	;	Overrun is not possible for current version. 	
  2875                              <1> 	;
  2876 00004737 AD                  <1> 	lodsd	
  2877 00004738 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2878 0000473A 3B1D[D06E0000]      <1> 	cmp	ebx, [u.count]
  2879 00004740 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2880                              <1> 	;
  2881                              <1> 	; 24/07/2015
  2882                              <1> 	; add bss section size to [u.break]
  2883 00004742 0105[D86E0000]      <1> 	add 	[u.break], eax
  2884                              <1> 	;
  2885 00004748 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2886                              <1> 	;cmp	ecx, [u.count]
  2887                              <1> 	;jnb	short sysexec_16
  2888                              <1> 		; cmp r5,u.count /
  2889                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2890 0000474B 890D[D06E0000]      <1> 	mov	[u.count], ecx ; required read count
  2891                              <1> 		; mov r5,u.count
  2892                              <1> 	;
  2893 00004751 EB2A                <1> 	jmp	short sysexec_16
  2894                              <1> 	;
  2895                              <1> sysexec_14:
  2896                              <1> 	; 23/06/2015
  2897                              <1> 	; insufficient (out of) memory
  2898 00004753 C705[FB6E0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2898 0000475B 0000                <1>
  2899 0000475D E984F3FFFF          <1> 	jmp	error
  2900                              <1> 	;
  2901                              <1> sysexec_15:
  2902                              <1> 	; 25/06/2015
  2903 00004762 0FB715[AC6B0000]    <1>         movzx   edx, word [i.size] ; file size
  2904 00004769 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2905 0000476B 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2906 0000476D 01D1                <1> 	add	ecx, edx ; [i.size]
  2907 0000476F 3B0D[D06E0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2908 00004775 77DC                <1> 	ja	short sysexec_14
  2909 00004777 8915[D06E0000]      <1> 	mov	[u.count], edx
  2910                              <1> sysexec_16:
  2911 0000477D 66A1[8C6E0000]      <1> 	mov	ax, [ii] ; i-number
  2912 00004783 E8EE0B0000          <1> 	call	readi
  2913                              <1> 		; add core+10,u.nread / add size of user data area 
  2914                              <1> 		                    ; / to u.nread
  2915                              <1> 		; br 2f
  2916                              <1> 	; 1:
  2917                              <1> 		; jsr r0,readi / read in rest of file
  2918                              <1> 	; 2:
  2919 00004788 8B0D[D46E0000]      <1> 	mov	ecx, [u.nread]
  2920 0000478E 010D[D86E0000]      <1> 	add	[u.break], ecx
  2921                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2922                              <1> 				    ; / user code
  2923                              <1> 		; add $core+14,u.break / plus data area
  2924                              <1> sysexec_17: ; 20/07/2015
  2925                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2926                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2927                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2928                              <1> 	;;mov	ax, [ii] ; i-number
  2929                              <1> 	;call	iclose
  2930                              <1> 	;	; jsr r0,iclose / does nothing
  2931 00004794 31C0                <1>         xor     eax, eax
  2932 00004796 FEC0                <1> 	inc	al
  2933 00004798 66A3[EA6E0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2934 0000479E 66A3[EC6E0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2935                              <1> 	; 02/07/2015
  2936 000047A4 833D[036F0000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2937 000047AB 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2938                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2939 000047AD 8B15[E86A0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2940 000047B3 8915[036F0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2941                              <1> sysexec_18:
  2942                              <1> 	; 18/10/2015
  2943                              <1> 	; 05/08/2015
  2944                              <1> 	; 29/07/2015
  2945 000047B9 8B2D[246F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2946                              <1> 			    ; list pointers (argument count)
  2947 000047BF FA                  <1> 	cli
  2948 000047C0 8B25[846A0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2949                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2950                              <1> 			    ; for this process	 
  2951                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2952                              <1> 	;xor	eax, eax ; 0
  2953 000047C6 FEC8                <1> 	dec	al ; eax = 0
  2954 000047C8 66BA2300            <1> 	mov	dx, UDATA
  2955 000047CC 6652                <1> 	push	dx  ; user's stack segment
  2956 000047CE 55                  <1> 	push	ebp ; user's stack pointer
  2957                              <1> 		    ; (points to number of arguments)
  2958 000047CF FB                  <1> 	sti
  2959 000047D0 9C                  <1> 	pushfd	; EFLAGS
  2960                              <1> 		; Set IF for enabling interrupts in user mode	
  2961                              <1> 	;or	dword [esp], 200h 
  2962                              <1> 	;
  2963                              <1> 	;mov	bx, UCODE
  2964                              <1> 	;push	bx ; user's code segment
  2965 000047D1 6A1B                <1> 	push	UCODE
  2966                              <1> 	;push	0
  2967 000047D3 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2968                              <1> 		; clr -(r5) / popped into ps when rti in 
  2969                              <1> 			  ; / sysrele is executed
  2970                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2971                              <1> 		                ; / in sysrele is executed
  2972                              <1> 		;mov r5,0f / load second copyz argument
  2973                              <1> 		;tst -(r5) / decrement r5
  2974 000047D4 8925[A46E0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2975                              <1> 	; 05/08/2015
  2976                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2977                              <1> 	; ('push dx' would cause to general protection fault, 
  2978                              <1> 	; after 'pop ds' etc.)
  2979                              <1> 	;
  2980                              <1> 	;; push dx ; ds (UDATA)
  2981                              <1> 	;; push dx ; es (UDATA)
  2982                              <1> 	;; push dx ; fs (UDATA)
  2983                              <1> 	;; push dx ; gs (UDATA)
  2984                              <1> 	;
  2985                              <1> 	; This is a trick to prevent general protection fault
  2986                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  2987 000047DA 8EC2                <1> 	mov 	es, dx ; UDATA
  2988 000047DC 06                  <1> 	push 	es ; ds (UDATA)
  2989 000047DD 06                  <1> 	push 	es ; es (UDATA)
  2990 000047DE 06                  <1> 	push 	es ; fs (UDATA)
  2991 000047DF 06                  <1> 	push	es ; gs (UDATA)
  2992 000047E0 66BA1000            <1> 	mov	dx, KDATA
  2993 000047E4 8EC2                <1> 	mov	es, dx
  2994                              <1> 	;
  2995                              <1> 	;; pushad simulation
  2996 000047E6 89E5                <1> 	mov	ebp, esp ; esp before pushad
  2997 000047E8 50                  <1> 	push	eax ; eax (0)
  2998 000047E9 50                  <1> 	push	eax ; ecx (0)
  2999 000047EA 50                  <1> 	push	eax ; edx (0)
  3000 000047EB 50                  <1> 	push	eax ; ebx (0)
  3001 000047EC 55                  <1> 	push	ebp ; esp before pushad
  3002 000047ED 50                  <1> 	push	eax ; ebp (0)
  3003 000047EE 50                  <1> 	push	eax ; esi (0)		
  3004 000047EF 50                  <1> 	push	eax ; edi (0)	
  3005                              <1> 	;
  3006 000047F0 A3[AC6E0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3007 000047F5 8925[A86E0000]      <1> 	mov	[u.usp], esp
  3008                              <1> 		; mov r5,u.r0 /
  3009                              <1> 		; sub $16.,r5 / skip 8 words
  3010                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3011                              <1> 		;             / effectively zeroes all regs
  3012                              <1> 			    ; / when sysrele is executed
  3013                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3014                              <1> 		; clr u.break
  3015                              <1> 		; mov r5,sp / point sp to user's stack
  3016                              <1> 	;
  3017 000047FB E908F3FFFF          <1> 	jmp	sysret0
  3018                              <1> 	;jmp	sysret
  3019                              <1> 		; br sysret3 / return to core image at $core
  3020                              <1> 
  3021                              <1> get_argp:
  3022                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  3023                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3024                              <1> 	; 18/10/2015 (nbase, ncount)
  3025                              <1> 	; 21/07/2015
  3026                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3027                              <1> 	; Get (virtual) address of argument from user's core memory
  3028                              <1> 	;
  3029                              <1> 	; INPUT:
  3030                              <1> 	;	esi = virtual address of argument pointer
  3031                              <1> 	; OUTPUT:
  3032                              <1> 	;	eax = virtual address of argument
  3033                              <1> 	;
  3034                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3035                              <1> 	;
  3036 00004800 833D[036F0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3037                              <1> 				    ; (the caller is kernel)
  3038                              <1>         ;jna	short get_argpk
  3039                              <1> 	; 03/02/2022
  3040 00004807 7719                <1> 	ja	short get_argp5
  3041                              <1> get_argpk:
  3042                              <1> 	; Argument is in kernel's memory space
  3043 00004809 66C705[206F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3043 00004811 10                  <1>
  3044 00004812 8935[1C6F0000]      <1> 	mov	[nbase], esi
  3045 00004818 8305[1C6F0000]04    <1> 	add	dword [nbase], 4
  3046 0000481F 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3047 00004821 C3                  <1> 	retn
  3048                              <1> get_argp5:
  3049 00004822 89F3                <1>      	mov	ebx, esi
  3050 00004824 E897E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3051 00004829 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  3052 0000482B A3[1C6F0000]        <1> 	mov 	[nbase], eax ; physical address	
  3053 00004830 66890D[206F0000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3054 00004837 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3055                              <1> 	;cmp	cx, ax ; 4
  3056                              <1> 	; 03/02/2022
  3057 0000483C 39C1                <1> 	cmp	ecx, eax
  3058 0000483E 734C                <1> 	jnb	short get_argp2
  3059 00004840 89F3                <1> 	mov	ebx, esi
  3060 00004842 01CB                <1> 	add	ebx, ecx
  3061 00004844 E877E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3062 00004849 7237                <1> 	jc	short get_argp_err
  3063                              <1> 	;push	esi
  3064 0000484B 89C6                <1> 	mov	esi, eax
  3065 0000484D 66870D[206F0000]    <1> 	xchg	cx, [ncount]
  3066 00004854 8735[1C6F0000]      <1> 	xchg	esi, [nbase]
  3067 0000485A B504                <1> 	mov	ch, 4
  3068 0000485C 28CD                <1> 	sub	ch, cl
  3069                              <1> get_argp0:
  3070 0000485E AC                  <1> 	lodsb
  3071                              <1> 	;push	ax
  3072                              <1> 	; 03/02/2022
  3073 0000485F 50                  <1> 	push	eax
  3074 00004860 FEC9                <1> 	dec	cl
  3075 00004862 75FA                <1>         jnz     short get_argp0
  3076 00004864 8B35[1C6F0000]      <1> 	mov	esi, [nbase]
  3077                              <1> 	; 21/07/2015
  3078 0000486A 0FB6C5              <1> 	movzx	eax, ch
  3079 0000486D 0105[1C6F0000]      <1> 	add	[nbase], eax
  3080 00004873 662905[206F0000]    <1> 	sub	[ncount], ax
  3081                              <1> get_argp1:
  3082 0000487A AC                  <1> 	lodsb
  3083 0000487B FECD                <1> 	dec	ch
  3084 0000487D 7423                <1>         jz      short get_argp3
  3085                              <1>         ;push	ax
  3086                              <1> 	; 03/02/2022
  3087 0000487F 50                  <1> 	push	eax
  3088 00004880 EBF8                <1> 	jmp     short get_argp1
  3089                              <1> get_argp_err:
  3090 00004882 A3[FB6E0000]        <1> 	mov	[u.error], eax
  3091 00004887 E95AF2FFFF          <1> 	jmp	error
  3092                              <1> get_argp2:
  3093                              <1> 	; 21/07/2015
  3094                              <1> 	;mov	eax, 4
  3095 0000488C 8B15[1C6F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3096 00004892 0105[1C6F0000]      <1> 	add	[nbase], eax
  3097 00004898 662905[206F0000]    <1> 	sub	[ncount], ax
  3098                              <1> 	;
  3099 0000489F 8B02                <1> 	mov	eax, [edx]
  3100 000048A1 C3                  <1> 	retn
  3101                              <1> get_argp3:
  3102 000048A2 B103                <1> 	mov	cl, 3
  3103                              <1> get_argp4:
  3104 000048A4 C1E008              <1> 	shl	eax, 8
  3105                              <1> 	;pop	dx
  3106                              <1> 	; 03/02/2022
  3107 000048A7 5A                  <1> 	pop	edx
  3108 000048A8 88D0                <1> 	mov 	al, dl
  3109 000048AA E2F8                <1>         loop    get_argp4
  3110                              <1> 	;pop	esi
  3111 000048AC C3                  <1> 	retn	
  3112                              <1> 
  3113                              <1> sysfstat:
  3114                              <1> 	; 03/02/2022
  3115                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3116                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3117                              <1> 	;
  3118                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3119                              <1> 	; on open files instead of files given by name. It puts the
  3120                              <1> 	; buffer address on the stack, gets the i-number and
  3121                              <1> 	; checks to see if the file is open for reading or writing.
  3122                              <1> 	; If the file is open for writing (i-number is negative)
  3123                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3124                              <1> 	; is made.	
  3125                              <1> 	;
  3126                              <1> 	; Calling sequence:
  3127                              <1> 	;	sysfstat; buf
  3128                              <1> 	; Arguments:
  3129                              <1> 	;	buf - buffer address
  3130                              <1> 	;
  3131                              <1> 	; Inputs: *u.r0 - file descriptor
  3132                              <1> 	; Outputs: buffer is loaded with file information
  3133                              <1> 	; ...............................................................
  3134                              <1> 	;				
  3135                              <1> 	; Retro UNIX 8086 v1 modification:
  3136                              <1> 	;       'sysfstat' system call has two arguments; so,
  3137                              <1> 	;	* 1st argument, file descriptor is in BX register
  3138                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3139                              <1> 
  3140                              <1> 	; / set status of open file
  3141                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3142 000048AD 51                  <1> 	push	ecx
  3143                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3144                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3145                              <1> 		; jsr r0,getf / get the files i-number
  3146                              <1> 	; BX = file descriptor (file number)
  3147 000048AE E8F2000000          <1> 	call	getf1
  3148                              <1> 	; 03/02/2022
  3149 000048B3 21C0                <1> 	and	eax, eax
  3150                              <1> 	;and	ax, ax ; i-number of the file
  3151                              <1> 		; tst	r1 / is it 0?
  3152                              <1> 	;jz	error
  3153                              <1> 		; beq error3 / yes, error
  3154 000048B5 750F                <1> 	jnz	short sysfstat1
  3155 000048B7 C705[FB6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3155 000048BF 0000                <1>
  3156 000048C1 E920F2FFFF          <1> 	jmp	error
  3157                              <1> sysfstat1:
  3158 000048C6 80FC80              <1> 	cmp	ah, 80h
  3159 000048C9 7222                <1>         jb      short sysstat1
  3160                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3161 000048CB 66F7D8              <1> 	neg	ax
  3162                              <1> 		; neg r1 / make it positive, then branch
  3163 000048CE EB1D                <1> 	jmp	short sysstat1
  3164                              <1> 		; br 1f / to 1f
  3165                              <1> sysstat:
  3166                              <1> 	; 03/02/2022
  3167                              <1> 	; 18/10/2015
  3168                              <1> 	; 07/10/2015
  3169                              <1> 	; 02/09/2015
  3170                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3171                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3172                              <1> 	;
  3173                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3174                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3175                              <1> 	; long and information about the file placed in it.	
  3176                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3177                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3178                              <1> 	; is then loaded and the results are given in the UNIX
  3179                              <1> 	; Programmers Manual sysstat (II).	
  3180                              <1> 	;
  3181                              <1> 	; Calling sequence:
  3182                              <1> 	;	sysstat; name; buf
  3183                              <1> 	; Arguments:
  3184                              <1> 	;	name - points to the name of the file
  3185                              <1> 	;	buf - address of a 34 bytes buffer
  3186                              <1> 	; Inputs: -
  3187                              <1> 	; Outputs: buffer is loaded with file information
  3188                              <1> 	; ...............................................................
  3189                              <1> 	;				
  3190                              <1> 	; Retro UNIX 8086 v1 modification: 
  3191                              <1> 	;       'sysstat' system call has two arguments; so,
  3192                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3193                              <1> 	;	to get sysstat system call arguments from the user;
  3194                              <1> 	;	* 1st argument, name is pointed to by BX register
  3195                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3196                              <1> 	;
  3197                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3198                              <1> 	;	      arguments which were in these registers;
  3199                              <1> 	;	      but, it returns by putting the 1st argument
  3200                              <1> 	;	      in 'u.namep' and the 2nd argument
  3201                              <1> 	;	      on top of stack. (1st argument is offset of the
  3202                              <1> 	;	      file/path name in the user's program segment.)		 	
  3203                              <1> 	
  3204                              <1> 	; / ; name of file; buffer - get files status
  3205                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3206 000048D0 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  3207 000048D6 51                  <1> 	push	ecx
  3208 000048D7 E8FC000000          <1> 	call	namei
  3209                              <1> 		; jsr r0,namei / get the i-number for the file
  3210                              <1> 	;jc	error
  3211                              <1> 		; br error3 / no such file, error
  3212 000048DC 730F                <1> 	jnc	short sysstat1
  3213                              <1> 	; pop 	ecx
  3214                              <1> sysstat_err0:
  3215                              <1> 	; 'file not found !' error
  3216 000048DE C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3216 000048E6 0000                <1>
  3217 000048E8 E9F9F1FFFF          <1> 	jmp	error
  3218                              <1> 
  3219                              <1> ;statx: db 0
  3220                              <1> 
  3221                              <1> sysstat1: ; 1:
  3222 000048ED E8B0080000          <1> 	call	iget
  3223                              <1> 		; jsr r0,iget / get the i-node into core
  3224                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3225                              <1> 	; 02/09/2015
  3226 000048F2 8F05[CC6E0000]      <1> 	pop	dword [u.base]
  3227                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3228 000048F8 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3229 000048FD 730A                <1> 	jnc 	short sysstat2
  3230                              <1> sysstat_err1:
  3231 000048FF A3[FB6E0000]        <1> 	mov	dword [u.error], eax ; error code
  3232 00004904 E9DDF1FFFF          <1> 	jmp	error
  3233                              <1> sysstat2:
  3234 00004909 A0[8C6E0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3235 0000490E AA                  <1> 	stosb
  3236 0000490F FF05[CC6E0000]      <1> 	inc 	dword [u.base]
  3237                              <1> 	;dec 	cx
  3238                              <1> 	; 03/02/2022
  3239 00004915 49                  <1> 	dec	ecx
  3240 00004916 7505                <1> 	jnz	short sysstat3
  3241 00004918 E835000000          <1> 	call	sysstat_gpa
  3242                              <1> 	;jc	short sysstat_err1
  3243                              <1> sysstat3:
  3244 0000491D A0[8D6E0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3245 00004922 AA                  <1> 	stosb
  3246                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3247 00004923 FF05[CC6E0000]      <1> 	inc 	dword [u.base]
  3248                              <1> 	;;dec 	word [u.pcount]
  3249                              <1> 	;dec	cx
  3250                              <1> 	; 03/02/2022
  3251 00004929 49                  <1> 	dec	ecx
  3252 0000492A 7505                <1> 	jnz	short sysstat4
  3253 0000492C E821000000          <1> 	call	sysstat_gpa
  3254                              <1> 	;jc	short sysstat_err1	
  3255                              <1> sysstat4:
  3256 00004931 BE[A86B0000]        <1> 	mov	esi, inode
  3257                              <1> 		; mov $inode,r2 / r2 points to i-node
  3258                              <1> sysstat5: ; 1:
  3259 00004936 A4                  <1> 	movsb
  3260                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3261 00004937 FF05[CC6E0000]      <1> 	inc 	dword [u.base]
  3262                              <1> 	;;dec 	word [u.pcount]
  3263                              <1> 	;dec	cx
  3264                              <1> 	; 03/02/2022
  3265 0000493D 49                  <1> 	dec	ecx
  3266 0000493E 7505                <1> 	jnz	short sysstat6
  3267 00004940 E80D000000          <1> 	call	sysstat_gpa
  3268                              <1> 	;jc	short sysstat_err1
  3269                              <1> sysstat6:		
  3270 00004945 81FE[C86B0000]      <1> 	cmp	esi, inode + 32
  3271                              <1> 		; cmp r2,$inode+32 / done?
  3272 0000494B 75E9                <1> 	jne	short sysstat5
  3273                              <1> 		; bne 1b / no, go back
  3274 0000494D E9B4F1FFFF          <1> 	jmp	sysret
  3275                              <1> 		; br sysret3 / return through sysret
  3276                              <1> 	;
  3277                              <1> sysstat_gpa: ; get physical address of file status buffer
  3278                              <1> 	; 02/09/2015
  3279 00004952 8B1D[CC6E0000]      <1> 	mov 	ebx, [u.base]
  3280                              <1> 	; 07/10/2015
  3281 00004958 E863E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3282                              <1> 	;jc	short sysstat_gpa1
  3283 0000495D 72A0                <1> 	jc	short sysstat_err1
  3284                              <1> 	; 18/10/2015
  3285 0000495F 89C7                <1> 	mov	edi, eax ; physical address
  3286                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3287                              <1> ;sysstat_gpa1:
  3288 00004961 C3                  <1> 	retn
  3289                              <1> 
  3290                              <1> fclose:
  3291                              <1> 	; 03/02/2022
  3292                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3293                              <1> 	;            (32 bit offset pointer modification)
  3294                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3295                              <1> 	;
  3296                              <1> 	; Given the file descriptor (index to the u.fp list)
  3297                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3298                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3299                              <1> 	; u.fp list is cleared. If all the processes that opened
  3300                              <1> 	; that file close it, then fsp etry is freed and the file
  3301                              <1> 	; is closed. If not a return is taken. 
  3302                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3303                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3304                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3305                              <1> 	; a check is made to see if the file is special.	
  3306                              <1> 	;
  3307                              <1> 	; INPUTS ->
  3308                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3309                              <1> 	;    u.fp - list of entries in the fsp table
  3310                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3311                              <1> 	; OUTPUTS ->
  3312                              <1> 	;    r1 - contains the same file descriptor
  3313                              <1> 	;    r2 - contains i-number
  3314                              <1> 	;
  3315                              <1> 	; ((AX = R1))
  3316                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3317                              <1> 	;
  3318                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3319                              <1> 	;              if i-number of the file is 0. (error)  	
  3320                              <1> 
  3321                              <1> 	;movzx	edx, ax ; **
  3322                              <1> 	; 03/02/2022
  3323                              <1> 	;movzx	edx, al
  3324 00004962 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3325 00004964 50                  <1> 	push	eax ; ***
  3326                              <1> 	;push	ax ; ***
  3327                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3328                              <1> 			     ; / the index to u.fp list)
  3329 00004965 E839000000          <1> 	call	getf
  3330                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3331                              <1> 			    ; / cdev has device =, u.fofp 
  3332                              <1> 			    ; / points to 3rd word of fsp entry
  3333 0000496A 6683F801            <1> 	cmp	ax, 1 ; r1
  3334                              <1> 		; tst r1 / is i-number 0?
  3335 0000496E 7231                <1> 	jb	short fclose_2
  3336                              <1> 		; beq 1f / yes, i-node not active so return
  3337                              <1> 		; tst (r0)+ / no, jump over error return
  3338 00004970 89D3                <1> 	mov	ebx, edx ; **
  3339                              <1> 	; 03/02/2022
  3340 00004972 89C2                <1> 	mov	edx, eax ; *
  3341                              <1> 	;mov 	dx, ax ; *
  3342                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3343                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3344                              <1> 			    ; / which is index to u.fp ; **
  3345 00004974 C683[B26E0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3346                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3347 0000497B 8B1D[BC6E0000]      <1> 	mov	ebx, [u.fofp]
  3348                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3349                              <1> fclose_0:
  3350 00004981 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3351                              <1> 		; decb 2(r1) / decrement the number of processes 
  3352                              <1> 			   ; / that have opened the file
  3353 00004984 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3354                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3355                              <1> 	;
  3356                              <1> 	; 03/02/2022
  3357 00004986 52                  <1> 	push	edx ; *
  3358                              <1> 	;push	dx ; *
  3359                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3360                              <1> 	;xor	ax, ax ; 0
  3361                              <1> 	; 03/02/2022
  3362 00004987 31C0                <1> 	xor	eax, eax
  3363 00004989 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3364                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3365 0000498D 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3366                              <1> 		; tstb	3(r1) / has this file been deleted
  3367 00004990 20C0                <1> 	and	al, al
  3368 00004992 7407                <1> 	jz	short fclose_1
  3369                              <1> 		; beq 2f / no, branch
  3370                              <1> 	; 03/02/2022
  3371 00004994 89D0                <1> 	mov	eax, edx
  3372                              <1> 	;mov	ax, dx ; *
  3373                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3374                              <1> 	; AX = inode number
  3375 00004996 E85E040000          <1> 	call	anyi
  3376                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3377                              <1> 			    ; / check if file appears in fsp again
  3378                              <1> fclose_1: ; 2:
  3379                              <1> 	; 03/02/2022
  3380 0000499B 58                  <1> 	pop	eax ; * 
  3381                              <1> 	;pop	ax ; *
  3382                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3383 0000499C E8C4100000          <1> 	call	iclose ; close if it is special file 
  3384                              <1> 		; jsr r0,iclose / check to see if its a special file
  3385                              <1> fclose_2: ; 1:
  3386                              <1> 	; 03/02/2022
  3387 000049A1 58                  <1> 	pop	eax ; ***
  3388                              <1> 	;pop	ax ; ***
  3389                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3390 000049A2 C3                  <1> 	retn
  3391                              <1> 		; rts r0
  3392                              <1> 
  3393                              <1> getf:	; / get the device number and the i-number of an open file
  3394                              <1> 	; 03/02/2022
  3395                              <1> 	; 13/05/2015
  3396                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3397                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3398                              <1> 	;
  3399 000049A3 89C3                <1> 	mov	ebx, eax
  3400                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3401                              <1> 	; 03/02/2022
  3402 000049A5 29C0                <1> 	sub	eax, eax
  3403                              <1> 	;
  3404 000049A7 83FB0A              <1> 	cmp	ebx, 10
  3405                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3406 000049AA 732B                <1>         jnb	short getf2 ; 13/05/2015
  3407                              <1> 	;jnb	error
  3408                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3409                              <1> 			    ; / index in fsp table
  3410                              <1> 	; 03/02/2022
  3411 000049AC 8A83[B26E0000]      <1> 	mov	al, [ebx+u.fp]
  3412                              <1> 	;mov	bl, [ebx+u.fp]
  3413                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3414                              <1> 		                  ; / in fsp table
  3415                              <1> 	; 03/02/2022
  3416 000049B2 08C0                <1> 	or	al, al
  3417 000049B4 7421                <1> 	jz	short getf2
  3418                              <1> 	;or	bl, bl
  3419                              <1> 	;jnz	short getf3
  3420                              <1> 	;;jz	short getf4
  3421                              <1> 		; beq 1f / if its zero return
  3422                              <1> ;getf2:
  3423                              <1> ;	; 'File not open !' error (ax=0)
  3424                              <1> ;	sub	eax, eax
  3425                              <1> ;	retn
  3426                              <1> 
  3427                              <1> getf3:	
  3428                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3429                              <1> 	;
  3430                              <1> 	; 'fsp' table (10 bytes/entry)
  3431                              <1> 	; bit 15				   bit 0
  3432                              <1> 	; ---|-------------------------------------------
  3433                              <1> 	; r/w|		i-number of open file
  3434                              <1> 	; ---|-------------------------------------------
  3435                              <1> 	;		   device number
  3436                              <1> 	; -----------------------------------------------
  3437                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3438                              <1> 	; -----------------------------------------------
  3439                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3440                              <1> 	; ----------------------|------------------------
  3441                              <1> 	;  flag that says file 	| number of processes
  3442                              <1> 	;   has been deleted	| that have file open 
  3443                              <1> 	; ----------------------|------------------------
  3444                              <1> 	;
  3445                              <1> 	;mov	eax, 10
  3446                              <1> 	; 03/02/2022
  3447 000049B6 B30A                <1> 	mov	bl, 10
  3448 000049B8 F6E3                <1> 	mul	bl
  3449 000049BA BB[726C0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3450 000049BF 01C3                <1> 	add	ebx, eax
  3451                              <1> 		; asl r1
  3452                              <1> 		; asl r1 / multiply by 8 to get index into 
  3453                              <1> 		       ; / fsp table entry
  3454                              <1> 		; asl r1
  3455                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3456                              <1> 			      ; / in the fsp entry
  3457 000049C1 891D[BC6E0000]      <1> 	mov	[u.fofp], ebx
  3458                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3459                              <1> 			      ; / in fsp entry in u.fofp
  3460 000049C7 4B                  <1> 	dec	ebx
  3461 000049C8 4B                  <1> 	dec	ebx
  3462                              <1> 	;mov	al, [ebx]
  3463 000049C9 668B03              <1> 	mov	ax, [ebx]
  3464                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3465 000049CC 66A3[906E0000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3466                              <1> 			     ;;dev number is in 1 byte
  3467                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3468 000049D2 4B                  <1> 	dec	ebx
  3469 000049D3 4B                  <1> 	dec	ebx
  3470 000049D4 668B03              <1> 	mov	ax, [ebx]
  3471                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3472                              <1> getf2:	; 03/02/2022
  3473                              <1> getf4:	; 1:
  3474 000049D7 C3                  <1> 	retn
  3475                              <1> 		; rts r0
  3476                              <1> 
  3477                              <1> namei:
  3478                              <1> 	; 03/02/2022
  3479                              <1> 	; 18/10/2015 (nbase, ncount)
  3480                              <1> 	; 12/10/2015
  3481                              <1> 	; 21/08/2015
  3482                              <1> 	; 18/07/2015
  3483                              <1> 	; 02/07/2015
  3484                              <1> 	; 17/06/2015
  3485                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3486                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3487                              <1> 	;
  3488                              <1> 	; 'namei' takes a file path name and returns i-number of
  3489                              <1> 	; the file in the current directory or the root directory
  3490                              <1> 	; (if the first character of the pathname is '/').	
  3491                              <1> 	;
  3492                              <1> 	; INPUTS ->
  3493                              <1> 	;    u.namep - points to a file path name
  3494                              <1> 	;    u.cdir - i-number of users directory
  3495                              <1> 	;    u.cdev - device number on which user directory resides	
  3496                              <1> 	; OUTPUTS ->
  3497                              <1> 	;    r1 - i-number of file
  3498                              <1> 	;    cdev
  3499                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3500                              <1> 	;               occurs in the search for file path name.
  3501                              <1> 	;	        If no match u.dirb points to the end of 
  3502                              <1> 	;               the directory and r1 = i-number of the current
  3503                              <1> 	;	        directory.	
  3504                              <1> 	; ((AX = R1))
  3505                              <1> 	;
  3506                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3507                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3508                              <1> 	;
  3509                              <1> 
  3510 000049D8 66A1[B06E0000]      <1> 	mov	ax, [u.cdir]
  3511                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3512                              <1> 			      ; / in r1
  3513 000049DE 668B15[F06E0000]    <1> 	mov	dx, [u.cdrv]
  3514 000049E5 668915[906E0000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3515                              <1> 				    ; device/drive number is in 1 byte, 
  3516                              <1> 				    ; not in 1 word!
  3517                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3518                              <1> 				; / into cdev
  3519                              <1> 	; 12/10/2015
  3520                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3521                              <1>       	 ; convert virtual (pathname) addr to physical address
  3522 000049EC E823010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3523                              <1> 		; esi = physical address of [u.namep]
  3524                              <1> 		; ecx = byte count in the page
  3525 000049F1 803E2F              <1> 	cmp	byte [esi], '/'
  3526                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3527 000049F4 751D                <1> 	jne	short namei_1
  3528                              <1> 		; bne 1f
  3529 000049F6 FF05[C46E0000]      <1> 	inc	dword [u.namep]
  3530                              <1> 		; inc u.namep / go to next char
  3531                              <1> 	; 03/02/2022
  3532 000049FC 49                  <1> 	dec	ecx
  3533                              <1> 	;dec	cx ; remain byte count in the page
  3534 000049FD 7506                <1> 	jnz	short namei_0
  3535                              <1> 	; 12/10/2015
  3536 000049FF E810010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3537                              <1> 		; esi = physical address (page start + offset)
  3538                              <1> 		; ecx = byte count in the page
  3539 00004A04 4E                  <1> 	dec	esi
  3540                              <1> namei_0:
  3541 00004A05 46                  <1> 	inc 	esi  ; go to next char
  3542 00004A06 66A1[9A6E0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3543                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3544 00004A0C C605[906E0000]00    <1> 	mov	byte [cdev], 0
  3545                              <1> 		; clr cdev / clear device number
  3546                              <1> namei_1: ; 1:
  3547 00004A13 F606FF              <1> 	test	byte [esi], 0FFh
  3548                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3549 00004A16 74BF                <1> 	jz	short getf4
  3550                              <1> 	;jz	nig
  3551                              <1> 		; tstb *u.namep / is the character in file name a nul
  3552                              <1> 		; beq nig / yes, end of file name reached; 
  3553                              <1> 			; / branch to "nig"
  3554                              <1> namei_2: ; 1:
  3555                              <1> 	; 18/10/2015
  3556 00004A18 8935[1C6F0000]      <1> 	mov 	[nbase], esi
  3557 00004A1E 66890D[206F0000]    <1> 	mov 	[ncount], cx
  3558                              <1> 	;
  3559                              <1> 	;mov	dx, 2
  3560 00004A25 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3561 00004A27 E84A080000          <1> 	call	access
  3562                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3563                              <1> 	; 'access' will not return here if user has not "r" permission !
  3564                              <1> 	; 03/02/2022
  3565 00004A2C F605[A96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3566                              <1> 	;test 	word [i.flgs], 4000h
  3567                              <1> 		; bit $40000,i.flgs / directory i-node?
  3568 00004A33 746A                <1>         jz      short namei_err
  3569                              <1> 		; beq error3 / no, got an error
  3570                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3571 00004A35 31C0                <1> 	xor	eax, eax
  3572 00004A37 A3[C86E0000]        <1> 	mov	[u.off], eax ; 0
  3573 00004A3C 66A1[AC6B0000]      <1> 	mov	ax, [i.size]
  3574 00004A42 A3[C06E0000]        <1> 	mov	[u.dirp], eax
  3575                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3576                              <1> 		; clr u.off / u.off is file offset used by user
  3577 00004A47 C705[BC6E0000]-     <1> 	mov	dword [u.fofp], u.off
  3577 00004A4D [C86E0000]          <1>
  3578                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3579                              <1> 				  ; / the offset portion of fsp entry
  3580                              <1> namei_3: ; 2:
  3581 00004A51 C705[CC6E0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3581 00004A57 [DE6E0000]          <1>
  3582                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3583                              <1> 				    ; / copied from a directory
  3584 00004A5B C705[D06E0000]0A00- <1> 	mov 	dword [u.count], 10 	
  3584 00004A63 0000                <1>
  3585                              <1>  		; mov $10.,u.count / u.count is byte count 
  3586                              <1> 				 ; / for reads and writes
  3587 00004A65 66A1[8C6E0000]      <1> 	mov 	ax, [ii]
  3588                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3589 00004A6B FE05[0D6F0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3590 00004A71 E800090000          <1>     	call	readi
  3591                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3592                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3593 00004A76 8B0D[D46E0000]      <1> 	mov 	ecx, [u.nread]
  3594 00004A7C 09C9                <1> 	or 	ecx, ecx
  3595                              <1> 		; tst u.nread
  3596 00004A7E 741B                <1> 	jz	short nib
  3597                              <1> 		; ble nib / gives error return
  3598                              <1> 	;
  3599 00004A80 668B1D[DE6E0000]    <1> 	mov 	bx, [u.dirbuf]
  3600 00004A87 6621DB              <1> 	and 	bx, bx       
  3601                              <1> 		; tst u.dirbuf /
  3602 00004A8A 7522                <1> 	jnz	short namei_4
  3603                              <1> 		; bne 3f / branch when active directory entry 
  3604                              <1> 		       ; / (i-node word in entry non zero)
  3605 00004A8C A1[C86E0000]        <1> 	mov	eax, [u.off]
  3606 00004A91 83E80A              <1> 	sub	eax, 10
  3607 00004A94 A3[C06E0000]        <1> 	mov	[u.dirp], eax
  3608                              <1> 		; mov u.off,u.dirp
  3609                              <1> 		; sub $10.,u.dirp
  3610 00004A99 EBB6                <1> 	jmp	short namei_3
  3611                              <1> 		; br 2b
  3612                              <1> 
  3613                              <1> 	; 18/07/2013
  3614                              <1> nib: 
  3615 00004A9B 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3616 00004A9D F9                  <1> 	stc
  3617                              <1> nig:
  3618 00004A9E C3                  <1> 	retn
  3619                              <1> 
  3620                              <1> namei_err:
  3621                              <1> 	; 16/06/2015
  3622 00004A9F C705[FB6E0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3622 00004AA7 0000                <1>
  3623 00004AA9 E938F0FFFF          <1> 	jmp	error
  3624                              <1> 
  3625                              <1> namei_4: ; 3:
  3626                              <1> 	; 18/10/2015
  3627                              <1> 	; 12/10/2015
  3628                              <1> 	; 21/08/2015
  3629                              <1> 	; 18/07/2015
  3630 00004AAE 8B2D[C46E0000]      <1> 	mov	ebp, [u.namep]
  3631                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3632 00004AB4 BF[E06E0000]        <1> 	mov 	edi, u.dirbuf + 2
  3633                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3634                              <1> 	; 18/10/2015
  3635 00004AB9 8B35[1C6F0000]      <1> 	mov	esi, [nbase]	
  3636 00004ABF 668B0D[206F0000]    <1> 	mov	cx, [ncount]
  3637                              <1> 	;
  3638 00004AC6 6621C9              <1> 	and	cx, cx
  3639 00004AC9 7505                <1> 	jnz	short namei_5	
  3640                              <1> 	;
  3641 00004ACB E84A000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3642                              <1> 		; esi = physical address (page start + offset)
  3643                              <1> 		; ecx = byte count in the page
  3644                              <1> namei_5: ; 3:
  3645 00004AD0 45                  <1> 	inc	ebp ; 18/07/2015
  3646 00004AD1 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3647                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3648 00004AD2 08C0                <1> 	or 	al, al
  3649 00004AD4 741C                <1> 	jz 	short namei_7
  3650                              <1> 		; beq 3f / if char is nul, then the last char in string
  3651                              <1> 			; / has been moved
  3652 00004AD6 3C2F                <1> 	cmp	al, '/'
  3653                              <1> 		; cmp r4,$'/ / is char a </>
  3654 00004AD8 7418                <1> 	je 	short namei_7
  3655                              <1> 		; beq 3f
  3656                              <1> 	; 03/02/2022
  3657 00004ADA 49                  <1> 	dec	ecx	
  3658                              <1> 	; 12/10/2015
  3659                              <1> 	;dec	cx ; remain byte count in the page
  3660 00004ADB 7505                <1> 	jnz	short namei_6
  3661 00004ADD E838000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3662                              <1> 		; esi = physical address (page start + offset)
  3663                              <1> 		; ecx = byte count in the page
  3664                              <1> namei_6:
  3665 00004AE2 81FF[E86E0000]      <1>         cmp     edi, u.dirbuf + 10
  3666                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3667                              <1> 				     ; / all 8 bytes of file name
  3668 00004AE8 74E6                <1> 	je	short namei_5
  3669                              <1> 		; beq 3b
  3670 00004AEA AE                  <1> 	scasb	
  3671                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3672                              <1> 			      ; / char read from directory
  3673 00004AEB 74E3                <1> 	je 	short namei_5
  3674                              <1> 		; beq 3b / branch if chars match
  3675                              <1> namei_9:
  3676 00004AED E95FFFFFFF          <1>         jmp    namei_3 ; 2b
  3677                              <1> 		; br 2b / file names do not match go to next directory entry
  3678                              <1> namei_7: ; 3:
  3679 00004AF2 81FF[E86E0000]      <1> 	cmp	edi, u.dirbuf + 10
  3680                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3681 00004AF8 7406                <1> 	je	short namei_8
  3682                              <1> 		; beq 3f
  3683 00004AFA 8A27                <1> 	mov 	ah, [edi]
  3684                              <1> 	;inc 	edi 
  3685 00004AFC 20E4                <1> 	and 	ah, ah
  3686                              <1> 		; tstb (r3)+ /
  3687                              <1>         ;jnz	namei_3
  3688                              <1> 		; bne 2b
  3689                              <1> 	; 03/02/2020
  3690 00004AFE 75ED                <1> 	jnz	short namei_9
  3691                              <1> namei_8: ; 3
  3692 00004B00 892D[C46E0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3693                              <1> 		; mov r2,u.namep / u.namep points to char 
  3694                              <1> 			       ; / following a / or nul
  3695                              <1> 	;mov	bx, [u.dirbuf]
  3696                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3697                              <1> 				; / entry to r1
  3698 00004B06 20C0                <1> 	and 	al, al
  3699                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3700                              <1> 		      ;  / if r4 = </> then go to next directory
  3701                              <1> 	; mov	ax, bx
  3702 00004B08 66A1[DE6E0000]      <1> 	mov 	ax, [u.dirbuf] ; 17/06/2015
  3703                              <1>   	; 03/02/2022
  3704 00004B0E E903FFFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3705                              <1> 	;jnz	namei_2 
  3706                              <1> 		; bne 1b
  3707                              <1> 	; AX = i-number of the file
  3708                              <1> ;;nig:
  3709 00004B13 C3                  <1> 	retn
  3710                              <1> 		; tst (r0)+ / gives non-error return
  3711                              <1> ;;nib:
  3712                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3713                              <1> 		       ; ax = 0 -> file not found 
  3714                              <1> ;;	stc	; 27/05/2013
  3715                              <1> ;;	retn
  3716                              <1> 		; rts r0
  3717                              <1> 
  3718                              <1> trans_addr_nmbp:
  3719                              <1> 	; 03/02/2022
  3720                              <1> 	; 18/10/2015
  3721                              <1> 	; 12/10/2015
  3722 00004B14 8B2D[C46E0000]      <1> 	mov 	ebp, [u.namep]
  3723                              <1> trans_addr_nm:
  3724                              <1> 	; 03/02/2022
  3725                              <1> 	; Convert virtual (pathname) address to physical address
  3726                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3727                              <1> 	; 18/10/2015
  3728                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3729                              <1> 	; 02/07/2015
  3730                              <1> 	; 17/06/2015
  3731                              <1> 	; 16/06/2015
  3732                              <1> 	;
  3733                              <1> 	; INPUTS: 
  3734                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3735                              <1> 	;	[u.pgdir] = user's page directory
  3736                              <1> 	; OUTPUT:
  3737                              <1> 	;       esi = physical address of the pathname
  3738                              <1> 	;	ecx = remain byte count in the page
  3739                              <1> 	;
  3740                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3741                              <1> 	;
  3742                              <1> 
  3743                              <1> 	; 03/02/2022
  3744 00004B1A 29C9                <1> 	sub	ecx, ecx
  3745                              <1> 
  3746 00004B1C 833D[036F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3747 00004B23 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3748                              <1> 				     ; it is already physical address
  3749 00004B25 50                  <1>    	push	eax	
  3750 00004B26 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3751 00004B28 E893E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3752 00004B2D 7204                <1> 	jc	short tr_addr_nm_err
  3753                              <1> 	; 18/10/2015
  3754                              <1> 	; eax = physical address 
  3755                              <1> 	; cx = remain byte count in page (1-4096) 
  3756                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3757 00004B2F 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3758 00004B31 58                  <1> 	pop	eax 
  3759 00004B32 C3                  <1> 	retn
  3760                              <1> 
  3761                              <1> tr_addr_nm_err:
  3762 00004B33 A3[FB6E0000]        <1> 	mov	[u.error], eax
  3763                              <1> 	;pop 	eax
  3764 00004B38 E9A9EFFFFF          <1> 	jmp	error
  3765                              <1> 
  3766                              <1> trans_addr_nmk:
  3767                              <1> 	; 12/10/2015
  3768                              <1> 	; 02/07/2015
  3769 00004B3D 8B35[C46E0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3770                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3771                              <1> 	; 03/02/2022
  3772 00004B43 B510                <1> 	mov	ch, PAGE_SIZE/256
  3773 00004B45 C3                  <1> 	retn
  3774                              <1> 
  3775                              <1> syschdir:
  3776                              <1> 	; 03/02/2022
  3777                              <1> 	; / makes the directory specified in the argument
  3778                              <1> 	; / the current directory
  3779                              <1> 	;
  3780                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3781                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3782                              <1> 	;
  3783                              <1> 	; 'syschdir' makes the directory specified in its argument
  3784                              <1> 	; the current working directory.
  3785                              <1> 	;
  3786                              <1> 	; Calling sequence:
  3787                              <1> 	;	syschdir; name
  3788                              <1> 	; Arguments:
  3789                              <1> 	;	name - address of the path name of a directory
  3790                              <1> 	;	       terminated by nul byte.	
  3791                              <1> 	; Inputs: -
  3792                              <1> 	; Outputs: -
  3793                              <1> 	; ...............................................................
  3794                              <1> 	;				
  3795                              <1> 	; Retro UNIX 8086 v1 modification:
  3796                              <1> 	;	 The user/application program puts address of 
  3797                              <1> 	;	 the path name in BX register as 'syschdir' 
  3798                              <1> 	; 	 system call argument.
  3799                              <1> 
  3800 00004B46 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  3801                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3802 00004B4C E887FEFFFF          <1> 	call	namei
  3803                              <1> 		; jsr r0,namei / find its i-number
  3804                              <1> 	;jc	error
  3805                              <1> 		; br error3
  3806 00004B51 730F                <1> 	jnc	short syschdir0
  3807                              <1> 	; 'directory not found !' error
  3808 00004B53 C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3808 00004B5B 0000                <1>
  3809 00004B5D E984EFFFFF          <1> 	jmp	error
  3810                              <1> syschdir0:
  3811                              <1> 	; 03/02/2022
  3812 00004B62 B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3813 00004B64 E80D070000          <1> 	call	access
  3814                              <1> 		; jsr r0,access; 2 / get i-node into core
  3815                              <1> 	; 03/02/2022
  3816 00004B69 F605[A96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3817                              <1> 	;test	word [i.flgs], 4000h
  3818                              <1> 		; bit $40000,i.flgs / is it a directory?
  3819                              <1> 	;jz	error 
  3820                              <1> 		; beq error3 / no error
  3821 00004B70 750F                <1> 	jnz	short syschdir1
  3822 00004B72 C705[FB6E0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3822 00004B7A 0000                <1>
  3823 00004B7C E965EFFFFF          <1> 	jmp	error
  3824                              <1> syschdir1:
  3825 00004B81 66A3[B06E0000]      <1> 	mov	[u.cdir], ax
  3826                              <1> 		; mov r1,u.cdir / move i-number to users 
  3827                              <1> 			      ; / current directory
  3828 00004B87 66A1[906E0000]      <1> 	mov	ax, [cdev]
  3829 00004B8D 66A3[F06E0000]      <1> 	mov	[u.cdrv], ax
  3830                              <1> 		; mov cdev,u.cdev / move its device to users 
  3831                              <1> 			        ; / current device
  3832 00004B93 E96EEFFFFF          <1> 	jmp	sysret
  3833                              <1> 		; br sysret3
  3834                              <1> 	
  3835                              <1> syschmod: ; < change mode of file >
  3836                              <1> 	; 03/02/2022
  3837                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3838                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3839                              <1> 	;
  3840                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3841                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3842                              <1> 	; changed to 'mode'.
  3843                              <1> 	;
  3844                              <1> 	; Calling sequence:
  3845                              <1> 	;	syschmod; name; mode
  3846                              <1> 	; Arguments:
  3847                              <1> 	;	name - address of the file name
  3848                              <1> 	;	       terminated by null byte.
  3849                              <1> 	;	mode - (new) mode/flags < attributes >
  3850                              <1> 	;	
  3851                              <1> 	; Inputs: -
  3852                              <1> 	; Outputs: -
  3853                              <1> 	; ...............................................................
  3854                              <1> 	;				
  3855                              <1> 	; Retro UNIX 8086 v1 modification: 
  3856                              <1> 	;       'syschmod' system call has two arguments; so,
  3857                              <1> 	;	* 1st argument, name is pointed to by BX register
  3858                              <1> 	;	* 2nd argument, mode is in CX register
  3859                              <1> 	;
  3860                              <1> 	; Mode bits (Flags):
  3861                              <1> 	;	bit 0 - write permission for non-owner (1)
  3862                              <1> 	;	bit 1 - read permission for non-owner (2)
  3863                              <1> 	;	bit 2 - write permission for owner (4)
  3864                              <1> 	;	bit 3 - read permission for owner (8)
  3865                              <1> 	;	bit 4 - executable flag (16) 	
  3866                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3867                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3868                              <1> 	;	bit 12 - large file flag (4096)
  3869                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3870                              <1> 	;	bit 14 - directory flag (16384)
  3871                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3872                              <1> 
  3873                              <1> 	; / name; mode
  3874 00004B98 E812000000          <1> 	call	isown
  3875                              <1> 		;jsr r0,isown / get the i-node and check user status
  3876                              <1> 	; 03/02/2022
  3877 00004B9D F605[A96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3878                              <1> 	;test	word [i.flgs], 4000h
  3879                              <1> 		; bit $40000,i.flgs / directory?
  3880 00004BA4 7402                <1> 	jz	short syschmod1
  3881                              <1> 		; beq 2f / no
  3882                              <1> 	; AL = (new) mode
  3883 00004BA6 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3884                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3885                              <1> 			   ; / executable modes
  3886                              <1> syschmod1: ; 2:
  3887 00004BA8 A2[A86B0000]        <1> 	mov	[i.flgs], al	
  3888                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3889 00004BAD EB42                <1> 	jmp	short isown1
  3890                              <1> 		; br 1f
  3891                              <1> 
  3892                              <1> isown:
  3893                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3894                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3895                              <1> 	;
  3896                              <1> 	; 'isown' is given a file name (the 1st argument).
  3897                              <1> 	;  It find the i-number of that file via 'namei' 
  3898                              <1> 	;  then gets the i-node into core via 'iget'.
  3899                              <1> 	;  It then tests to see if the user is super user. 
  3900                              <1> 	;  If not, it cheks to see if the user is owner of 
  3901                              <1> 	;  the file. If he is not an error occurs.
  3902                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3903                              <1> 	;  the inode has been modificed and the 2nd argument of
  3904                              <1> 	;  the call is put in r2.
  3905                              <1> 	;
  3906                              <1> 	; INPUTS ->
  3907                              <1> 	;    arguments of syschmod and syschown calls
  3908                              <1> 	; OUTPUTS ->
  3909                              <1> 	;    u.uid - id of user
  3910                              <1> 	;    imod - set to a 1
  3911                              <1> 	;    r2 - contains second argument of the system call				 	
  3912                              <1> 	;
  3913                              <1> 	;   ((AX=R2) output as 2nd argument)
  3914                              <1> 	;
  3915                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  3916                              <1> 	;
  3917                              <1> 		; jsr r0,arg2 / u.namep points to file name
  3918                              <1> 	;; ! 2nd argument on top of stack !
  3919                              <1> 	;; 22/06/2015 - 32 bit modifications
  3920                              <1> 	;; 07/07/2013
  3921 00004BAF 891D[C46E0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  3922 00004BB5 51                  <1> 	push 	ecx ;; 2nd argument
  3923                              <1> 	;;
  3924 00004BB6 E81DFEFFFF          <1> 	call	namei
  3925                              <1> 		; jsr r0,namei / get its i-number
  3926                              <1>        ; Retro UNIX 8086 v1 modification !
  3927                              <1>        ; ax = 0 -> file not found 
  3928                              <1> 	;and	ax, ax
  3929                              <1> 	;jz	error
  3930                              <1> 	;jc	error ; 27/05/2013
  3931                              <1> 		; br error3
  3932 00004BBB 730F                <1> 	jnc	short isown0
  3933                              <1> 	; 'file not found !' error
  3934 00004BBD C705[FB6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3934 00004BC5 0000                <1>
  3935 00004BC7 E91AEFFFFF          <1> 	jmp	error
  3936                              <1> isown0:
  3937 00004BCC E8D1050000          <1> 	call	iget
  3938                              <1> 		; jsr r0,iget / get i-node into core
  3939 00004BD1 A0[F26E0000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  3940 00004BD6 08C0                <1> 	or	al, al
  3941                              <1> 		; tstb u.uid / super user?
  3942 00004BD8 7417                <1> 	jz	short isown1
  3943                              <1> 		; beq 1f / yes, branch
  3944 00004BDA 3A05[AB6B0000]      <1> 	cmp	al, [i.uid]
  3945                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  3946                              <1> 				 ; / the file
  3947                              <1> 	;jne	error
  3948                              <1> 		; beq 1f / yes
  3949                              <1> 		; jmp error3 / no, error
  3950 00004BE0 740F                <1> 	je	short isown1
  3951                              <1> 
  3952 00004BE2 C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  3952 00004BEA 0000                <1>
  3953                              <1> 			;  'permission denied !' error
  3954 00004BEC E9F5EEFFFF          <1> 	jmp	error
  3955                              <1> isown1: ; 1:
  3956 00004BF1 E8B6060000          <1> 	call	setimod
  3957                              <1> 		; jsr r0,setimod / indicates 
  3958                              <1> 		;	       ; / i-node has been modified
  3959 00004BF6 58                  <1> 	pop	eax ; 2nd argument
  3960                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  3961                              <1> 		       ; / (u.off put on stack with 2nd arg)
  3962 00004BF7 C3                  <1> 	retn
  3963                              <1> 		; rts r0
  3964                              <1> 
  3965                              <1> ;;arg:  ; < get system call arguments >
  3966                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  3967                              <1> 	; of form:
  3968                              <1> 	;	sys 'routine' ; arg1
  3969                              <1> 	;		or
  3970                              <1> 	;	sys 'routine' ; arg1 ; arg2
  3971                              <1> 	;		or
  3972                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  3973                              <1> 	;	
  3974                              <1> 	; INPUTS ->
  3975                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  3976                              <1> 	;	This pointers's value is actually the value of
  3977                              <1> 	;	update pc at the the trap to sysent (unkni) is
  3978                              <1> 	;	made to process the sys instruction
  3979                              <1> 	;    r0 - contains the return address for the routine
  3980                              <1> 	;	that called arg. The data in the word pointer 
  3981                              <1> 	;	to by the return address is used as address
  3982                              <1> 	;	in which the extracted argument is stored   		
  3983                              <1> 	;    	
  3984                              <1> 	; OUTPUTS ->
  3985                              <1> 	;    'address' - contains the extracted argument 
  3986                              <1> 	;    u.sp+18 - is incremented by 2 
  3987                              <1> 	;    r1 - contains the extracted argument
  3988                              <1> 	;    r0 - points to the next instruction to be
  3989                              <1> 	;	 executed in the calling routine.
  3990                              <1> 	;
  3991                              <1>   
  3992                              <1> 	; mov u.sp,r1
  3993                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  3994                              <1> 			; / into argument of arg2
  3995                              <1> 	; add $2,18.(r1) / point pc on stack 
  3996                              <1> 			      ; / to next system argument
  3997                              <1> 	; rts r0
  3998                              <1> 
  3999                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4000                              <1> 	; 'arg2' takes first argument in system call
  4001                              <1> 	;  (pointer to name of the file) and puts it in location
  4002                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4003                              <1> 	;  and on top of the stack
  4004                              <1> 	;	
  4005                              <1> 	; INPUTS ->
  4006                              <1> 	;    u.sp, r0
  4007                              <1> 	;    	
  4008                              <1> 	; OUTPUTS ->
  4009                              <1> 	;    u.namep
  4010                              <1> 	;    u.off 
  4011                              <1> 	;    u.off pushed on stack
  4012                              <1> 	;    r1
  4013                              <1> 	;
  4014                              <1> 
  4015                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4016                              <1> 				; / first arg in sys call
  4017                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4018                              <1> 				; / second arg in sys call
  4019                              <1> 	; mov r0,r1 / r0 points to calling routine
  4020                              <1> 	; mov (sp),r0 / put operation code back in r0
  4021                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4022                              <1> 			; / on stack
  4023                              <1> 	; jmp (r1) / return to calling routine
  4024                              <1> 
  4025                              <1> syschown: ; < change owner of file >
  4026                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4027                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4028                              <1> 	;
  4029                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4030                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4031                              <1> 	; changed to 'owner'
  4032                              <1> 	;
  4033                              <1> 	; Calling sequence:
  4034                              <1> 	;	syschown; name; owner
  4035                              <1> 	; Arguments:
  4036                              <1> 	;	name - address of the file name
  4037                              <1> 	;	       terminated by null byte.
  4038                              <1> 	;	owner - (new) owner (number/ID)
  4039                              <1> 	;	
  4040                              <1> 	; Inputs: -
  4041                              <1> 	; Outputs: -
  4042                              <1> 	; ...............................................................
  4043                              <1> 	;				
  4044                              <1> 	; Retro UNIX 8086 v1 modification: 
  4045                              <1> 	;       'syschown' system call has two arguments; so,
  4046                              <1> 	;	* 1st argument, name is pointed to by BX register
  4047                              <1> 	;	* 2nd argument, owner number is in CX register
  4048                              <1> 	;
  4049                              <1> 	; / name; owner
  4050 00004BF8 E8B2FFFFFF          <1> 	call	isown
  4051                              <1> 		; jsr r0,isown / get the i-node and check user status
  4052 00004BFD 803D[F26E0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4053                              <1> 		; tstb u.uid / super user
  4054 00004C04 7418                <1> 	jz	short syschown1
  4055                              <1> 		; beq 2f / yes, 2f
  4056 00004C06 F605[A86B0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4057                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4058                              <1> 	;jnz	error
  4059                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4060 00004C0D 740F                <1> 	jz	short syschown1
  4061                              <1> 	; 'permission denied !'
  4062 00004C0F C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4062 00004C17 0000                <1>
  4063 00004C19 E9C8EEFFFF          <1> 	jmp	error
  4064                              <1> syschown1: ; 2:
  4065                              <1> 	; AL = owner (number/ID)
  4066 00004C1E A2[AB6B0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4067                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4068                              <1> 			       ; / in the i-node
  4069 00004C23 E9DEEEFFFF          <1> 	jmp	sysret
  4070                              <1> 	; 1: 
  4071                              <1> 		; jmp sysret4
  4072                              <1> 	; 3:
  4073                              <1> 		; jmp	error
  4074                              <1> 
  4075                              <1> systime: ; / get time of year
  4076                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4077                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4078                              <1> 	;
  4079                              <1> 	; 20/06/2013
  4080                              <1> 	; 'systime' gets the time of the year.
  4081                              <1> 	; The present time is put on the stack.
  4082                              <1> 	;
  4083                              <1> 	; Calling sequence:
  4084                              <1> 	;	systime
  4085                              <1> 	; Arguments: -
  4086                              <1> 	;	
  4087                              <1> 	; Inputs: -
  4088                              <1> 	; Outputs: sp+2, sp+4 - present time
  4089                              <1> 	; ...............................................................
  4090                              <1> 	;	
  4091                              <1> 	; Retro UNIX 8086 v1 modification: 
  4092                              <1> 	;       'systime' system call will return to the user
  4093                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4094                              <1> 	;
  4095                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4096                              <1> 	;	system call for PC compatibility !!		 	
  4097                              <1> 
  4098 00004C28 E8FCE9FFFF          <1> 	call 	epoch
  4099 00004C2D A3[AC6E0000]        <1> 	mov 	[u.r0], eax
  4100                              <1> 		; mov s.time,4(sp)
  4101                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4102                              <1> 				   ; / on the stack
  4103                              <1> 		; br sysret4
  4104 00004C32 E9CFEEFFFF          <1> 	jmp	sysret 
  4105                              <1> 
  4106                              <1> sysstime: ; / set time
  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> 	; 'sysstime' sets the time. Only super user can use this call.
  4111                              <1> 	;
  4112                              <1> 	; Calling sequence:
  4113                              <1> 	;	sysstime
  4114                              <1> 	; Arguments: -
  4115                              <1> 	;	
  4116                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4117                              <1> 	; Outputs: -
  4118                              <1> 	; ...............................................................
  4119                              <1> 	;	
  4120                              <1> 	; Retro UNIX 8086 v1 modification: 
  4121                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4122                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4123                              <1> 	; 
  4124                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4125                              <1> 	;	to get sysstime system call arguments from the user;
  4126                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4127                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4128                              <1> 	;
  4129                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4130                              <1> 	;	system call for PC compatibility !!	
  4131                              <1> 
  4132 00004C37 803D[F26E0000]00    <1> 	cmp	byte [u.uid], 0
  4133                              <1> 		; tstb u.uid / is user the super user
  4134                              <1> 	;ja	error
  4135                              <1> 		; bne error4 / no, error
  4136 00004C3E 760F                <1> 	jna	short systime1
  4137                              <1> 	; 'permission denied !'
  4138 00004C40 C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4138 00004C48 0000                <1>
  4139 00004C4A E997EEFFFF          <1> 	jmp	error
  4140                              <1> systime1:
  4141                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4142                              <1> 	; EBX = unix (epoch) time (from user)
  4143 00004C4F 89D8                <1> 	mov	eax, ebx
  4144 00004C51 E853EBFFFF          <1> 	call 	set_date_time
  4145                              <1> 		; mov 4(sp),s.time
  4146                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4147 00004C56 E9ABEEFFFF          <1> 	jmp	sysret
  4148                              <1> 		; br sysret4
  4149                              <1> 
  4150                              <1> sysbreak:
  4151                              <1> 	; 18/10/2015
  4152                              <1> 	; 07/10/2015
  4153                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4154                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4155                              <1> 	;
  4156                              <1> 	; 'sysbreak' sets the programs break points. 
  4157                              <1> 	; It checks the current break point (u.break) to see if it is
  4158                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4159                              <1> 	; even address (if it was odd) and the area between u.break
  4160                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4161                              <1> 	; in u.break and control is passed to 'sysret'.
  4162                              <1> 	;
  4163                              <1> 	; Calling sequence:
  4164                              <1> 	;	sysbreak; addr
  4165                              <1> 	; Arguments: -
  4166                              <1> 	;	
  4167                              <1> 	; Inputs: u.break - current breakpoint
  4168                              <1> 	; Outputs: u.break - new breakpoint 
  4169                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4170                              <1> 	; ...............................................................
  4171                              <1> 	;	
  4172                              <1> 	; Retro UNIX 8086 v1 modification:
  4173                              <1> 	;	The user/application program puts breakpoint address
  4174                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4175                              <1> 	; 	(argument transfer method 1)
  4176                              <1> 	;
  4177                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4178                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4179                              <1> 	;  NOTE:
  4180                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4181                              <1> 	;	'u.break' address) of user's memory for original unix's
  4182                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4183                              <1> 
  4184                              <1> 		; mov u.break,r1 / move users break point to r1
  4185                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4186                              <1> 		; blos 1f / yes, 1f
  4187                              <1> 	; 23/06/2015
  4188 00004C5B 8B2D[D86E0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4189                              <1> 	;and	ebp, ebp
  4190                              <1> 	;jz	short sysbreak_3 
  4191                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4192                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4193 00004C61 8B15[A46E0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4194 00004C67 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4195                              <1> 	; 07/10/2015
  4196 00004C6A 891D[D86E0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4197                              <1> 	;
  4198 00004C70 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4199                              <1> 			   ; with top of user's stack (virtual!)
  4200 00004C72 7327                <1> 	jnb	short sysbreak_3
  4201                              <1> 		; cmp r1,sp / is it the same or higher 
  4202                              <1> 			  ; / than the stack?
  4203                              <1> 		; bhis 1f / yes, 1f
  4204 00004C74 89DE                <1> 	mov	esi, ebx
  4205 00004C76 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4206 00004C78 7621                <1> 	jna	short sysbreak_3 
  4207                              <1> 	;push	ebx
  4208                              <1> sysbreak_1:
  4209 00004C7A 89EB                <1> 	mov	ebx, ebp  
  4210 00004C7C E83FE5FFFF          <1> 	call	get_physical_addr ; get physical address
  4211 00004C81 0F82ACFEFFFF        <1> 	jc	tr_addr_nm_err
  4212                              <1> 	; 18/10/2015
  4213 00004C87 89C7                <1> 	mov	edi, eax 
  4214 00004C89 29C0                <1> 	sub	eax, eax ; 0
  4215                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4216 00004C8B 39CE                <1> 	cmp	esi, ecx
  4217 00004C8D 7302                <1> 	jnb	short sysbreak_2
  4218 00004C8F 89F1                <1> 	mov	ecx, esi
  4219                              <1> sysbreak_2:
  4220 00004C91 29CE                <1> 	sub	esi, ecx
  4221 00004C93 01CD                <1> 	add	ebp, ecx
  4222 00004C95 F3AA                <1> 	rep 	stosb
  4223 00004C97 09F6                <1> 	or	esi, esi
  4224 00004C99 75DF                <1> 	jnz	short sysbreak_1
  4225                              <1> 	;
  4226                              <1> 		; bit $1,r1 / is it an odd address
  4227                              <1> 		; beq 2f / no, its even
  4228                              <1> 		; clrb (r1)+ / yes, make it even
  4229                              <1> 	; 2: / clear area between the break point and the stack
  4230                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4231                              <1> 		; bhis 1f / yes, quit
  4232                              <1> 		; clr (r1)+ / clear word
  4233                              <1> 		; br 2b / go back
  4234                              <1> 	;pop	ebx
  4235                              <1> sysbreak_3: ; 1:
  4236                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4237                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4238                              <1> 			; / in u.break (set new break point)
  4239                              <1> 		; br sysret4 / br sysret
  4240 00004C9B E966EEFFFF          <1> 	jmp	sysret
  4241                              <1> 
  4242                              <1> maknod: 
  4243                              <1> 	; 12/02/2022
  4244                              <1> 	; 03/02/2022
  4245                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4246                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4247                              <1> 	;
  4248                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4249                              <1> 	; for this i-node in the current directory.
  4250                              <1> 	;
  4251                              <1> 	; INPUTS ->
  4252                              <1> 	;    r1 - contains mode
  4253                              <1> 	;    ii - current directory's i-number	
  4254                              <1> 	;    	
  4255                              <1> 	; OUTPUTS ->
  4256                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4257                              <1> 	;    i.flgs - flags in new i-node 
  4258                              <1> 	;    i.uid - filled with u.uid
  4259                              <1> 	;    i.nlks - 1 is put in the number of links
  4260                              <1> 	;    i.ctim - creation time				
  4261                              <1> 	;    i.ctim+2 - modification time
  4262                              <1> 	;    imod - set via call to setimod
  4263                              <1> 	;	
  4264                              <1> 	; ((AX = R1)) input
  4265                              <1> 	;
  4266                              <1> 	; (Retro UNIX Prototype : 
  4267                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4268                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4269                              <1> 
  4270                              <1> 	; / r1 contains the mode
  4271 00004CA0 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4272                              <1> 		; bis $100000,r1 / allocate flag set
  4273 00004CA3 6650                <1> 	push	ax ; *
  4274                              <1> 		; mov r1,-(sp) / put mode on stack
  4275                              <1> 	; 31/07/2013
  4276 00004CA5 66A1[8C6E0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4277                              <1> 		; mov ii,r1 / move current i-number to r1
  4278 00004CAB B201                <1> 	mov	dl, 1 ; owner flag mask
  4279 00004CAD E8C4050000          <1> 	call	access	
  4280                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4281                              <1> 	; 03/02/2022
  4282 00004CB2 50                  <1> 	push	eax ; **
  4283                              <1> 	;push	ax
  4284                              <1> 		; mov r1,-(sp) / put i-number on stack
  4285 00004CB3 66B82800            <1> 	mov	ax, 40
  4286                              <1> 		; mov $40.,r1 / r1 = 40
  4287                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4288 00004CB7 6640                <1> 	inc	ax
  4289                              <1> 		; inc r1 / r1 = r1 + 1
  4290 00004CB9 E87D060000          <1> 	call	imap
  4291                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4292                              <1> 			    ; /	inode map in r2 & m
  4293                              <1>   
  4294                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4295                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4296                              <1> 
  4297                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4298                              <1> 	;	       Inode count must be checked here
  4299                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4300                              <1> 
  4301                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4302                              <1> 	; (inode count check)
  4303                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4304                              <1> 
  4305 00004CBE 730F                <1> 	jnc	short maknod2
  4306                              <1> 
  4307                              <1> 	; no free inode in inode table !
  4308 00004CC0 C705[FB6E0000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4308 00004CC8 0000                <1>
  4309                              <1> 			; miscellaneous/other errors
  4310 00004CCA E917EEFFFF          <1> 	jmp	error	
  4311                              <1> maknod2: 	
  4312 00004CCF 8413                <1> 	test	[ebx], dl
  4313                              <1> 		; bitb mq,(r2) / is the i-node active
  4314 00004CD1 75E4                <1> 	jnz	short maknod1
  4315                              <1> 		; bne 1b / yes, try the next one
  4316 00004CD3 0813                <1> 	or	[ebx], dl
  4317                              <1> 		; bisb mq,(r2) / no, make it active 
  4318                              <1> 			     ; / (put a 1 in the bit map)
  4319 00004CD5 E8C8040000          <1> 	call	iget
  4320                              <1> 		; jsr r0,iget / get i-node into core
  4321                              <1> 	; 03/02/2022
  4322 00004CDA F605[A96B0000]80    <1> 	test	byte [i.flgs+1], 80h
  4323                              <1> 	;test	word [i.flgs], 8000h 
  4324                              <1> 		; tst i.flgs / is i-node already allocated
  4325 00004CE1 75D4                <1> 	jnz	short maknod1	
  4326                              <1> 		; blt 1b / yes, look for another one
  4327 00004CE3 66A3[DE6E0000]      <1> 	mov	[u.dirbuf], ax
  4328                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4329                              <1> 	; 03/02/2022
  4330 00004CE9 58                  <1> 	pop	eax ; **
  4331                              <1> 	;pop	ax
  4332                              <1> 		; mov (sp)+,r1 / get current i-number back
  4333 00004CEA E8B3040000          <1> 	call	iget
  4334                              <1> 		; jsr r0,iget / get i-node in core
  4335 00004CEF E8AAF7FFFF          <1> 	call	mkdir
  4336                              <1> 		; jsr r0,mkdir / make a directory entry 
  4337                              <1> 			     ; / in current directory
  4338 00004CF4 66A1[DE6E0000]      <1> 	mov	ax, [u.dirbuf]
  4339                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4340 00004CFA E8A3040000          <1> 	call	iget
  4341                              <1> 		; jsr r0,iget / get it into core
  4342                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4343                              <1> 	;mov	ecx, 8
  4344                              <1> 	; 03/02/2022 
  4345 00004CFF 29C9                <1> 	sub	ecx, ecx
  4346 00004D01 B108                <1> 	mov	cl, 8
  4347 00004D03 31C0                <1> 	xor	eax, eax ; 0
  4348 00004D05 BF[A86B0000]        <1> 	mov	edi, inode 
  4349 00004D0A F3AB                <1> 	rep	stosd
  4350                              <1> 	;
  4351 00004D0C 668F05[A86B0000]    <1> 	pop	word [i.flgs] ; *
  4352                              <1> 		; mov (sp)+,i.flgs / fill flags
  4353 00004D13 8A0D[F26E0000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4354 00004D19 880D[AB6B0000]      <1> 	mov 	[i.uid], cl
  4355                              <1> 		; movb u.uid,i.uid / user id	
  4356 00004D1F C605[AA6B0000]01    <1> 	mov     byte [i.nlks], 1
  4357                              <1> 		; movb $1,i.nlks / 1 link
  4358                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4359                              <1> 	;mov	eax, [s.time]
  4360                              <1> 	;mov 	[i.ctim], eax
  4361                              <1> 	 	; mov s.time,i.ctim / time created
  4362                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4363                              <1> 	; Retro UNIX 8086 v1 modification !
  4364                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4365                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4366                              <1> 	;call setimod
  4367                              <1> 		; jsr r0,setimod / set modified flag
  4368                              <1> 	;retn
  4369                              <1> 		; rts r0 / return
  4370                              <1> 	; 03/02/2022
  4371 00004D26 E981050000          <1> 	jmp	setimod
  4372                              <1> 
  4373                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4374                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4375                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4376                              <1> 	;
  4377                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4378                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4379                              <1> 	; The file descriptor refers to a file open for reading or
  4380                              <1> 	; writing. The read (or write) pointer is set as follows:
  4381                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4382                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4383                              <1> 	;	  current location plus offset.
  4384                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4385                              <1> 	;	  size of file plus offset.
  4386                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4387                              <1> 	;
  4388                              <1> 	; Calling sequence:
  4389                              <1> 	;	sysseek; offset; ptrname
  4390                              <1> 	; Arguments:
  4391                              <1> 	;	offset - number of bytes desired to move 
  4392                              <1> 	;		 the r/w pointer
  4393                              <1> 	;	ptrname - a switch indicated above
  4394                              <1> 	;
  4395                              <1> 	; Inputs: r0 - file descriptor 
  4396                              <1> 	; Outputs: -
  4397                              <1> 	; ...............................................................
  4398                              <1> 	;	
  4399                              <1> 	; Retro UNIX 8086 v1 modification: 
  4400                              <1> 	;       'sysseek' system call has three arguments; so,
  4401                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4402                              <1> 	;	* 2nd argument, offset is in CX register
  4403                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4404                              <1> 	;	
  4405                              <1> 
  4406 00004D2B E822000000          <1> 	call	seektell
  4407                              <1> 	; AX = u.count
  4408                              <1> 	; BX = *u.fofp
  4409                              <1> 		; jsr r0,seektell / get proper value in u.count
  4410                              <1> 		; add u.base,u.count / add u.base to it
  4411 00004D30 0305[CC6E0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4412 00004D36 8903                <1> 	mov	[ebx], eax
  4413                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4414 00004D38 E9C9EDFFFF          <1> 	jmp	sysret
  4415                              <1> 		; br sysret4
  4416                              <1> 
  4417                              <1> systell: ; / get the r/w pointer
  4418                              <1> 	; 03/02/2022
  4419                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4420                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4421                              <1> 	;
  4422                              <1> 	; Retro UNIX 8086 v1 modification:
  4423                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4424                              <1> 	; 	    it returns with error !
  4425                              <1> 	; Inputs: r0 - file descriptor 
  4426                              <1> 	; Outputs: r0 - file r/w pointer
  4427                              <1> 
  4428                              <1> 	;xor	ecx, ecx ; 0
  4429                              <1> 	;mov	edx, 1 ; 05/08/2013
  4430                              <1> 	; 03/02/2022
  4431 00004D3D 29D2                <1> 	sub	edx, edx
  4432 00004D3F FEC2                <1> 	inc	dl
  4433                              <1> 	; edx = 1
  4434                              <1> 	;call 	seektell
  4435 00004D41 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4436                              <1> 	;mov	ebx, [u.fofp]
  4437 00004D46 8B03                <1> 	mov	eax, [ebx]
  4438 00004D48 A3[AC6E0000]        <1> 	mov	[u.r0], eax
  4439 00004D4D E9B4EDFFFF          <1> 	jmp	sysret
  4440                              <1> 
  4441                              <1> ; Original unix v1 'systell' system call:
  4442                              <1> 		; jsr r0,seektell
  4443                              <1> 		; br error4
  4444                              <1> 
  4445                              <1> seektell:
  4446                              <1> 	; 03/02/2022
  4447                              <1> 	; 03/01/2016
  4448                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4449                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4450                              <1> 	;
  4451                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4452                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4453                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4454                              <1> 	; getf. The i-node is brought into core and then u.count
  4455                              <1> 	; is checked to see it is a 0, 1, or 2.
  4456                              <1> 	; If it is 0 - u.count stays the same
  4457                              <1> 	;          1 - u.count = offset (u.fofp)
  4458                              <1> 	;	   2 - u.count = i.size (size of file)
  4459                              <1> 	; 	 		
  4460                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4461                              <1> 	;	Argument 1, file descriptor is in BX;
  4462                              <1> 	;	Argument 2, offset is in CX;
  4463                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4464                              <1> 	;
  4465                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4466                              <1> 	; call 	arg
  4467                              <1> 	;
  4468                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4469                              <1> 	;
  4470 00004D52 890D[CC6E0000]      <1> 	mov 	[u.base], ecx ; offset
  4471                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4472                              <1> seektell0:
  4473 00004D58 8915[D06E0000]      <1> 	mov 	[u.count], edx
  4474                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4475                              <1> 	; mov	ax, bx
  4476                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4477                              <1> 			     ; / (index in u.fp list)
  4478                              <1> 	; call	getf
  4479                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4480                              <1> 	; BX = file descriptor (file number)
  4481 00004D5E E842FCFFFF          <1> 	call	getf1
  4482                              <1> 	; 03/02/2022
  4483 00004D63 09C0                <1> 	or	eax, eax
  4484                              <1> 	;or	ax, ax ; i-number of the file
  4485                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4486                              <1> 		             ; / put it on the stack
  4487                              <1> 	;jz	error
  4488                              <1> 		; beq error4 / if i-number is 0, not active so error
  4489 00004D65 750F                <1> 	jnz	short seektell1
  4490 00004D67 C705[FB6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4490 00004D6F 0000                <1>
  4491 00004D71 E970EDFFFF          <1> 	jmp	error
  4492                              <1> seektell1:
  4493                              <1> 	;push	eax
  4494 00004D76 80FC80              <1> 	cmp	ah, 80h
  4495 00004D79 7203                <1> 	jb	short seektell2
  4496                              <1> 		; bgt .+4 / if its positive jump
  4497 00004D7B 66F7D8              <1> 	neg	ax
  4498                              <1> 		; neg r1 / if not make it positive
  4499                              <1> seektell2:
  4500 00004D7E E81F040000          <1> 	call	iget
  4501                              <1> 		; jsr r0,iget / get its i-node into core
  4502 00004D83 8B1D[BC6E0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4503 00004D89 803D[D06E0000]01    <1> 	cmp	byte [u.count], 1
  4504                              <1> 		; cmp u.count,$1 / is ptr name =1
  4505 00004D90 7705                <1> 	ja	short seektell3
  4506                              <1> 		; blt 2f / no its zero
  4507 00004D92 740A                <1> 	je	short seektell_4
  4508                              <1> 		; beq 1f / yes its 1
  4509 00004D94 31C0                <1> 	xor	eax, eax
  4510                              <1> 	;jmp	short seektell_5
  4511 00004D96 C3                  <1> 	retn
  4512                              <1> seektell3:
  4513                              <1> 	; 03/01/2016
  4514                              <1> 	;movzx  eax, word [i.size]
  4515 00004D97 66A1[AC6B0000]      <1> 	mov	ax, [i.size]
  4516                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4517                              <1>                                    ; / in file in u.count
  4518                              <1> 	;jmp	short seektell_5
  4519                              <1> 		; br 2f
  4520 00004D9D C3                  <1> 	retn
  4521                              <1> seektell_4: ; 1: / ptrname =1
  4522                              <1> 	;mov	ebx, [u.fofp]
  4523 00004D9E 8B03                <1> 	mov	eax, [ebx]
  4524                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4525                              <1> ;seektell_5: ; 2: / ptrname =0
  4526                              <1> 	;mov	[u.count], eax
  4527                              <1> 	;pop	eax 
  4528                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4529 00004DA0 C3                  <1> 	retn
  4530                              <1> 		; rts r0
  4531                              <1> 
  4532                              <1> sysintr: ; / set interrupt handling
  4533                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4534                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4535                              <1> 	;
  4536                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4537                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4538                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4539                              <1> 	; If one does the interrupt character in the tty buffer is
  4540                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4541                              <1> 	; 'sysret' is just called.	
  4542                              <1> 	;
  4543                              <1> 	; Calling sequence:
  4544                              <1> 	;	sysintr; arg
  4545                              <1> 	; Argument:
  4546                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4547                              <1> 	;	    - if 1, intterupts cause their normal result
  4548                              <1> 	;		 i.e force an exit.
  4549                              <1> 	;	    - if arg is a location within the program,
  4550                              <1> 	;		control is passed to that location when
  4551                              <1> 	;		an interrupt occurs.	
  4552                              <1> 	; Inputs: -
  4553                              <1> 	; Outputs: -
  4554                              <1> 	; ...............................................................
  4555                              <1> 	;	
  4556                              <1> 	; Retro UNIX 8086 v1 modification: 
  4557                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4558                              <1> 	;	then branches into sysquit.
  4559                              <1> 	;
  4560 00004DA1 66891D[EA6E0000]    <1> 	mov	[u.intr], bx
  4561                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4562                              <1> 		; br 1f / go into quit routine
  4563 00004DA8 E959EDFFFF          <1> 	jmp	sysret
  4564                              <1> 
  4565                              <1> sysquit:
  4566                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4567                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4568                              <1> 	;
  4569                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4570                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4571                              <1> 	; tty exists. If one does the interrupt character in the tty
  4572                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4573                              <1> 	; 'sysret' is just called.	
  4574                              <1> 	;
  4575                              <1> 	; Calling sequence:
  4576                              <1> 	;	sysquit; arg
  4577                              <1> 	; Argument:
  4578                              <1> 	;	arg - if 0, this call diables quit signals from the
  4579                              <1> 	;		typewriter (ASCII FS)
  4580                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4581                              <1> 	;		cease and a core image to be produced.
  4582                              <1> 	;		 i.e force an exit.
  4583                              <1> 	;	    - if arg is an addres in the program,
  4584                              <1> 	;		a quit causes control to sent to that
  4585                              <1> 	;		location.	
  4586                              <1> 	; Inputs: -
  4587                              <1> 	; Outputs: -
  4588                              <1> 	; ...............................................................
  4589                              <1> 	;	
  4590                              <1> 	; Retro UNIX 8086 v1 modification: 
  4591                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4592                              <1> 	;	then branches into 'sysret'.
  4593                              <1> 	;
  4594 00004DAD 66891D[EC6E0000]    <1> 	mov	[u.quit], bx
  4595 00004DB4 E94DEDFFFF          <1> 	jmp	sysret
  4596                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4597                              <1> 	;1:
  4598                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4599                              <1> 			      ; / to r1
  4600                              <1> 		; beq sysret4 / return to user
  4601                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4602                              <1> 			   ; / in the tty buffer
  4603                              <1> 		; br sysret4 / return to user
  4604                              <1> 
  4605                              <1> syssetuid: ; / set process id
  4606                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4607                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4608                              <1> 	;
  4609                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4610                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4611                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4612                              <1> 	; Only the super user can make this call.	
  4613                              <1> 	;
  4614                              <1> 	; Calling sequence:
  4615                              <1> 	;	syssetuid
  4616                              <1> 	; Arguments: -
  4617                              <1> 	;
  4618                              <1> 	; Inputs: (u.r0) - contains the process id.
  4619                              <1> 	; Outputs: -
  4620                              <1> 	; ...............................................................
  4621                              <1> 	;	
  4622                              <1> 	; Retro UNIX 8086 v1 modification: 
  4623                              <1> 	;       BL contains the (new) user ID of the current process
  4624                              <1> 
  4625                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4626 00004DB9 3A1D[F36E0000]      <1> 	cmp	bl, [u.ruid] 
  4627                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4628                              <1> 			       ; / id number
  4629 00004DBF 741E                <1> 	je	short setuid1
  4630                              <1> 		; beq 1f / yes
  4631 00004DC1 803D[F26E0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4632                              <1> 		; tstb u.uid / no, is current user the super user?
  4633                              <1> 	;ja	error
  4634                              <1> 		; bne error4 / no, error
  4635 00004DC8 760F                <1> 	jna	short setuid0
  4636 00004DCA C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4636 00004DD2 0000                <1>
  4637                              <1> 				; 'permission denied !' error
  4638 00004DD4 E90DEDFFFF          <1> 	jmp	error
  4639                              <1> setuid0:
  4640 00004DD9 881D[F36E0000]      <1> 	mov	[u.ruid], bl
  4641                              <1> setuid1: ; 1:
  4642 00004DDF 881D[F26E0000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4643                              <1> 		; movb r1,u.uid / put process id in u.uid
  4644                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4645 00004DE5 E91CEDFFFF          <1> 	jmp	sysret
  4646                              <1> 		; br sysret4 / system return
  4647                              <1> 
  4648                              <1> sysgetuid: ; < get user id >
  4649                              <1> 	; 03/02/2022
  4650                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4651                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4652                              <1> 	;
  4653                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4654                              <1> 	; The real user ID identifies the person who is logged in,
  4655                              <1> 	; in contradistinction to the effective user ID, which
  4656                              <1> 	; determines his access permission at each moment. It is thus
  4657                              <1> 	; useful to programs which operate using the 'set user ID'
  4658                              <1> 	; mode, to find out who invoked them.	
  4659                              <1> 	;
  4660                              <1> 	; Calling sequence:
  4661                              <1> 	;	syssetuid
  4662                              <1> 	; Arguments: -
  4663                              <1> 	;
  4664                              <1> 	; Inputs: -
  4665                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4666                              <1> 	; ...............................................................
  4667                              <1> 	;	
  4668                              <1> 	; Retro UNIX 8086 v1 modification: 
  4669                              <1> 	;       AL contains the real user ID at return.
  4670                              <1> 	;
  4671                              <1> 	;movzx 	eax, byte [u.ruid]
  4672                              <1> 	; 03/03/2022
  4673 00004DEA A0[F36E0000]        <1> 	mov	al, [u.ruid]
  4674 00004DEF A3[AC6E0000]        <1> 	mov	[u.r0], eax
  4675                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4676 00004DF4 E90DEDFFFF          <1> 	jmp	sysret
  4677                              <1> 		; br sysret4 / systerm return, sysret
  4678                              <1> 
  4679                              <1> anyi: 
  4680                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4681                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4682                              <1> 	;
  4683                              <1> 	; 'anyi' is called if a file deleted while open.
  4684                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4685                              <1> 	;
  4686                              <1> 	; INPUTS ->
  4687                              <1> 	;    r1 - contains an i-number
  4688                              <1> 	;    fsp - start of table containing open files
  4689                              <1> 	;
  4690                              <1> 	; OUTPUTS ->
  4691                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4692                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4693                              <1> 	;    if file not found - bit in i-node map is cleared
  4694                              <1> 	;    			 (i-node is freed)
  4695                              <1> 	;               all blocks related to i-node are freed
  4696                              <1> 	;	        all flags in i-node are cleared
  4697                              <1> 	; ((AX = R1)) input
  4698                              <1> 	;
  4699                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4700                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4701                              <1> 	;
  4702                              <1> 		; / r1 contains an i-number
  4703 00004DF9 BB[786C0000]        <1> 	mov	ebx, fsp
  4704                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4705                              <1> anyi_1: ; 1:
  4706 00004DFE 663B03              <1> 	cmp	ax, [ebx]
  4707                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4708 00004E01 7433                <1> 	je	short anyi_3
  4709                              <1> 		; beq 1f / yes, 1f
  4710 00004E03 66F7D8              <1> 	neg	ax
  4711                              <1> 		; neg r1 / no complement r1
  4712 00004E06 663B03              <1> 	cmp	ax, [ebx]
  4713                              <1> 		; cmp r1,(r2) / do they match now?
  4714 00004E09 742B                <1> 	je	short anyi_3
  4715                              <1> 		; beq 1f / yes, transfer
  4716                              <1> 		; / i-numbers do not match
  4717 00004E0B 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4718                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4719                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4720 00004E0E 81FB[6C6E0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4721                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4722                              <1> 				; / are we at last entry in the table
  4723 00004E14 72E8                <1> 	jb	short anyi_1
  4724                              <1> 		; blt 1b / no, check next entries i-number
  4725                              <1> 	;cmp	ax, 32768
  4726 00004E16 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4727                              <1> 		; tst r1 / yes, no match
  4728                              <1> 		; bge .+4
  4729 00004E19 7203                <1> 	jb	short anyi_2
  4730 00004E1B 66F7D8              <1> 	neg	ax
  4731                              <1> 		; neg r1 / make i-number positive
  4732                              <1> anyi_2:	
  4733 00004E1E E818050000          <1> 	call	imap
  4734                              <1> 		; jsr r0,imap / get address of allocation bit 
  4735                              <1> 			    ; / in the i-map in r2
  4736                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4737                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4738                              <1>  	; not	dx
  4739 00004E23 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4740                              <1>         ;and	[ebx], dx
  4741 00004E25 2013                <1> 	and 	[ebx], dl 
  4742                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4743 00004E27 E8A2040000          <1> 	call	itrunc
  4744                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4745 00004E2C 66C705[A86B0000]00- <1>  	mov 	word [i.flgs], 0
  4745 00004E34 00                  <1>
  4746                              <1> 		; clr i.flgs / clear all flags in the i-node
  4747 00004E35 C3                  <1> 	retn
  4748                              <1> 		;rts	r0 / return
  4749                              <1> anyi_3: ; 1: / i-numbers match
  4750 00004E36 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4751                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4752                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4753 00004E39 C3                  <1> 	retn
  4754                              <1> 		; rts r0
  2048                                  %include 'u3.s'        ; 10/05/2015
  2049                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2050                              <1> ; Last Modification: 03/02/2022
  2051                              <1> ; ----------------------------------------------------------------------------
  2052                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2053                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2054                              <1> ;
  2055                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2056                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2057                              <1> ; <Bell Laboratories (17/3/1972)>
  2058                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2059                              <1> ;
  2060                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2061                              <1> ;
  2062                              <1> ; ****************************************************************************
  2063                              <1> ; 15/09/2015
  2064                              <1> 
  2065                              <1> tswitch: ; Retro UNIX 386 v1
  2066                              <1> tswap:
  2067                              <1> 	; 01/09/2015
  2068                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2069                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2070                              <1> 	; time out swap, called when a user times out.
  2071                              <1> 	; the user is put on the low priority queue.
  2072                              <1> 	; This is done by making a link from the last user
  2073                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2074                              <1> 	; then he is swapped out.
  2075                              <1> 	;
  2076                              <1> 	; Retro UNIX 386 v1 modification ->
  2077                              <1> 	;       swap (software task switch) is performed by changing
  2078                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2079                              <1> 	;	as in Retro UNIX 8086 v1.
  2080                              <1> 	;
  2081                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2082                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2083                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2084                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2085                              <1> 	;	compatibles was using 1MB segmented memory 
  2086                              <1> 	;	in 8086/8088 times.
  2087                              <1> 	;
  2088                              <1> 	; INPUTS ->
  2089                              <1> 	;    u.uno - users process number
  2090                              <1> 	;    runq+4 - lowest priority queue
  2091                              <1> 	; OUTPUTS ->
  2092                              <1> 	;    r0 - users process number
  2093                              <1> 	;    r2 - lowest priority queue address
  2094                              <1> 	;
  2095                              <1> 	; ((AX = R0, BX = R2)) output
  2096                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2097                              <1> 	;
  2098 00004E3A A0[F56E0000]        <1> 	mov 	al, [u.uno]
  2099                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2100                              <1> 		; mov  $runq+4,r2 
  2101                              <1> 			; / move lowest priority queue address to r2
  2102 00004E3F E8CD000000          <1>         call 	putlu
  2103                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2104                              <1> 		             ; / u.uno's user
  2105                              <1> 
  2106                              <1> switch: ; Retro UNIX 386 v1
  2107                              <1> swap:
  2108                              <1> 	; 03/02/2022
  2109                              <1> 	; 02/09/2015
  2110                              <1> 	; 01/09/2015
  2111                              <1> 	; 31/08/2015
  2112                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2113                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2114                              <1> 	; 'swap' is routine that controls the swapping of processes
  2115                              <1> 	; in and out of core.
  2116                              <1> 	;
  2117                              <1> 	; Retro UNIX 386 v1 modification ->
  2118                              <1> 	;       swap (software task switch) is performed by changing
  2119                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2120                              <1> 	;	as in Retro UNIX 8086 v1.
  2121                              <1> 	;
  2122                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2123                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2124                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2125                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2126                              <1> 	;	compatibles was using 1MB segmented memory 
  2127                              <1> 	;	in 8086/8088 times.
  2128                              <1> 	;
  2129                              <1> 	; INPUTS ->
  2130                              <1> 	;    runq table - contains processes to run.
  2131                              <1> 	;    p.link - contains next process in line to be run.
  2132                              <1> 	;    u.uno - process number of process in core	
  2133                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2134                              <1> 	; OUTPUTS ->
  2135                              <1> 	;    (original unix v1 -> present process to its disk block)
  2136                              <1> 	;    (original unix v1 -> new process into core -> 
  2137                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2138                              <1> 	;	   for new process)
  2139                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2140                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2141                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2142                              <1> 	;	 for now, it will swap the process if there is not
  2143                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2144                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2145                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2146                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2147                              <1> 	;
  2148                              <1> 	;    u.pri -points to highest priority run Q.
  2149                              <1> 	;    r2 - points to the run queue.
  2150                              <1> 	;    r1 - contains new process number
  2151                              <1> 	;    r0 - points to place in routine or process that called
  2152                              <1> 	;	  swap all user parameters
  2153                              <1> 	;				
  2154                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2155                              <1> 	;
  2156                              <1> swap_0:
  2157                              <1> 		;mov $300,*$ps / processor priority = 6
  2158 00004E44 BE[9C6E0000]        <1> 	mov	esi, runq
  2159                              <1> 		; mov $runq,r2 / r2 points to runq table
  2160                              <1> swap_1: ; 1: / search runq table for highest priority process
  2161 00004E49 668B06              <1> 	mov	ax, [esi]
  2162 00004E4C 6621C0              <1> 	and 	ax, ax
  2163                              <1>        		; tst (r2)+ / are there any processes to run 
  2164                              <1> 			  ; / in this Q entry
  2165 00004E4F 7507                <1> 	jnz	short swap_2
  2166                              <1>        		; bne 1f / yes, process 1f
  2167                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2168                              <1> 			       ; / to end of table
  2169                              <1> 		; bne 1b / if not at end, go back
  2170 00004E51 E8E0000000          <1> 	call	idle
  2171                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2172                              <1> 				       ; / all queues are empty
  2173 00004E56 EBF1                <1> 	jmp	short swap_1
  2174                              <1> 		; br swap
  2175                              <1> swap_2: ; 1:
  2176 00004E58 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2177                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2178                              <1>  		; mov r2,u.pri / set present user to this run queue
  2179                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2180 00004E5B 38E0                <1> 	cmp	al, ah
  2181                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2182                              <1> 			      ; / in this Q to be run
  2183 00004E5D 740A                <1> 	je	short swap_3
  2184                              <1>        		; beq 1f / yes
  2185                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2186                              <1> 	;movzx	ebx, al
  2187 00004E5F 8AA3[176C0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2188 00004E65 8826                <1>        	mov	[esi], ah
  2189                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2190                              <1> 				       ; / in line into run queue
  2191 00004E67 EB05                <1> 	jmp	short swap_4
  2192                              <1>        		; br 2f
  2193                              <1> swap_3: ; 1:
  2194                              <1> 	;xor	dx, dx
  2195                              <1> 	; 03/02/2022
  2196 00004E69 31D2                <1> 	xor	edx, edx
  2197 00004E6B 668916              <1> 	mov	[esi], dx
  2198                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2199                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2200                              <1>       ; / in new process if required
  2201                              <1>        		; clr *$ps / clear processor status
  2202 00004E6E 8A25[F56E0000]      <1> 	mov 	ah, [u.uno]
  2203 00004E74 38C4                <1> 	cmp	ah, al
  2204                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2205                              <1> 			      ; / the process in core?
  2206 00004E76 743B                <1>        	je	short swap_8
  2207                              <1>        		; beq 2f / yes, don't have to swap
  2208                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2209                              <1> 			   ; / (address in routine that called swap)
  2210                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2211                              <1> 	; 01/09/2015
  2212                              <1> 	;mov	[u.usp], esp
  2213                              <1>        		; mov sp,u.usp / save stack pointer
  2214                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2215                              <1> 			       ; / to the stack pointer
  2216 00004E78 08E4                <1> 	or	ah, ah
  2217                              <1>        		; tstb u.uno / is the process # = 0
  2218 00004E7A 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2219                              <1> 		; beq  1f / yes, kill process by overwriting
  2220                              <1> 	; 02/09/2015
  2221 00004E7C 8925[A86E0000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2222                              <1> 	;
  2223 00004E82 E834000000          <1> 	call	wswap
  2224                              <1> 		;jsr r0,wswap / write out core to disk
  2225                              <1> 	 ; 31/08/2015
  2226                              <1> 	;movzx	ebx, al ; New (running) process number
  2227 00004E87 EB1C                <1> 	jmp 	short swap_7
  2228                              <1> swap_6:
  2229                              <1> 	; 31/08/2015
  2230                              <1> 	; Deallocate memory pages belong to the process
  2231                              <1> 	; which is being terminated
  2232                              <1> 	; 14/05/2015 ('sysexit')
  2233                              <1>  	; Deallocate memory pages of the process
  2234                              <1> 	; (Retro UNIX 386 v1 modification !)
  2235                              <1> 	;
  2236                              <1> 	; movzx ebx, al
  2237 00004E89 53                  <1> 	push	ebx
  2238 00004E8A A1[FF6E0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2239 00004E8F 8B1D[036F0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2240 00004E95 E86AE0FFFF          <1> 	call	deallocate_page_dir
  2241 00004E9A A1[F66E0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2242 00004E9F E8F8E0FFFF          <1> 	call	deallocate_page
  2243 00004EA4 5B                  <1> 	pop	ebx
  2244                              <1> swap_7: ;1: 
  2245                              <1> 	; 02/09/2015
  2246                              <1> 	; 31/08/2015
  2247                              <1> 	; 14/05/2015
  2248 00004EA5 C0E302              <1> 	shl	bl, 2 ; * 4 
  2249 00004EA8 8B83[346C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2250                              <1> 	;cli
  2251 00004EAE E831000000          <1> 	call	rswap
  2252                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2253                              <1> 		; jsr r0,rswap / read new process into core
  2254                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2255                              <1> 			      ; / to his program to its normal
  2256                              <1> 	; 01/09/2015
  2257                              <1> 	;mov	esp, [u.usp]	
  2258                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2259                              <1> 			     ; / new process stack
  2260                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2261                              <1> 			     ; / that just got swapped in, left off.,
  2262                              <1> 			     ; / i.e., transfer control to new process
  2263                              <1> 	;sti
  2264                              <1> swap_8: ;2:
  2265                              <1> 	; RETRO UNIX 8086 v1 modification !
  2266 00004EB3 C605[E86E0000]04    <1> 	mov	byte [u.quant], time_count 
  2267                              <1> 		; movb $30.,uquant / initialize process time quantum
  2268 00004EBA C3                  <1> 	retn
  2269                              <1> 		; rts r0 / return
  2270                              <1> 
  2271                              <1> wswap:  ; < swap out, swap to disk >
  2272                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2273                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2274                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2275                              <1> 	; appropriate disk area.
  2276                              <1> 	;
  2277                              <1> 	; Retro UNIX 386 v1 modification ->
  2278                              <1> 	;       User (u) structure content and the user's register content
  2279                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2280                              <1> 	;	saving 'u' structure and user registers for task switching).
  2281                              <1> 	;	u.usp - points to kernel stack address which contains
  2282                              <1> 	;		user's registers while entering system call.  
  2283                              <1> 	;	u.sp  - points to kernel stack address 
  2284                              <1> 	;		to return from system call -for IRET-.
  2285                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2286                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2287                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2288                              <1> 	;
  2289                              <1> 	; Retro UNIX 8086 v1 modification ->
  2290                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2291                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2292                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2293                              <1> 	;	compatibles was using 1MB segmented memory 
  2294                              <1> 	;	in 8086/8088 times.
  2295                              <1> 	;
  2296                              <1> 	; INPUTS ->
  2297                              <1> 	;    u.break - points to end of program
  2298                              <1> 	;    u.usp - stack pointer at the moment of swap
  2299                              <1> 	;    core - beginning of process program		
  2300                              <1> 	;    ecore - end of core 	
  2301                              <1> 	;    user - start of user parameter area		
  2302                              <1> 	;    u.uno - user process number	
  2303                              <1> 	;    p.dska - holds block number of process	
  2304                              <1> 	; OUTPUTS ->
  2305                              <1> 	;    swp I/O queue
  2306                              <1> 	;    p.break - negative word count of process 
  2307                              <1> 	;    r1 - process disk address	
  2308                              <1> 	;    r2 - negative word count
  2309                              <1> 	;
  2310                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2311                              <1> 	;
  2312                              <1> 	; INPUTS ->
  2313                              <1> 	;    u.uno - process number (to be swapped out)
  2314                              <1> 	; OUTPUTS ->
  2315                              <1> 	;    none
  2316                              <1> 	;
  2317                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2318                              <1> 	;
  2319 00004EBB 8B3D[F66E0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2320 00004EC1 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2321 00004EC6 BE[A46E0000]        <1> 	mov	esi, user ; active user (u) structure	
  2322 00004ECB F3A5                <1> 	rep	movsd
  2323                              <1> 	;
  2324 00004ECD 8B35[A86E0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2325                              <1> 			     ;      points to user registers)
  2326 00004ED3 8B0D[A46E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2327                              <1> 			     ; (for IRET)
  2328                              <1> 			     ; [u.sp] -> EIP (user)
  2329                              <1> 			     ; [u.sp+4]-> CS (user)
  2330                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2331                              <1> 			     ; [u.sp+12] -> ESP (user)
  2332                              <1> 			     ; [u.sp+16] -> SS (user)	
  2333 00004ED9 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2334 00004EDB 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2335                              <1> 			     ; (for IRET) 	
  2336 00004EDE C1E902              <1> 	shr	ecx, 2	     		
  2337 00004EE1 F3A5                <1> 	rep	movsd
  2338 00004EE3 C3                  <1> 	retn
  2339                              <1> 
  2340                              <1> 	; Original UNIX v1 'wswap' routine:
  2341                              <1> 	; wswap:
  2342                              <1> 		; mov *$30,u.emt / determines handling of emts
  2343                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2344                              <1> 				; / illegal instructions
  2345                              <1> 		; mov u.break,r2 / put process program break address in r2
  2346                              <1> 		; inc r2 / add 1 to it 
  2347                              <1> 		; bic $1,r2 / make it even
  2348                              <1> 		; mov r2,u.break / set break to an even location
  2349                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2350                              <1> 			     ; / at moment of swap in r3
  2351                              <1> 		; cmp r2,$core / is u.break less than $core
  2352                              <1> 		; blos 2f / yes
  2353                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2354                              <1>        		; bhis 2f / yes
  2355                              <1> 	; 1:
  2356                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2357                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2358                              <1> 		; bne 1b / no, keep packing
  2359                              <1> 	 	; br 1f / yes
  2360                              <1> 	; 2:
  2361                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2362                              <1> 	; 1:
  2363                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2364                              <1> 			   ; / (user up to end of stack gets written out)
  2365                              <1> 		; neg r2 / make it negative
  2366                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2367                              <1> 		; mov r2,swp+4 / word count
  2368                              <1> 		; movb u.uno,r1 / move user process number to r1
  2369                              <1> 		; asl r1 / x2 for index
  2370                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2371                              <1> 				     ; / into the p.break table
  2372                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2373                              <1> 				    ; /	for process to r1
  2374                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2375                              <1> 			     ; / (block number)
  2376                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2377                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2378                              <1> 	; 1:
  2379                              <1>        		; tstb swp+1 / is lt done writing?
  2380                              <1>        		; bne 1b / no, wait
  2381                              <1> 		; rts r0 / yes, return to swap
  2382                              <1> 
  2383                              <1> rswap:  ; < swap in, swap from disk >
  2384                              <1> 	; 15/09/2015
  2385                              <1> 	; 28/08/2015
  2386                              <1> 	; 14/05/2015
  2387                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2388                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2389                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2390                              <1> 	; from disk into core.
  2391                              <1> 	;
  2392                              <1> 	; Retro UNIX 386 v1 modification ->
  2393                              <1> 	;       User (u) structure content and the user's register content
  2394                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2395                              <1> 	;	saving 'u' structure and user registers for task switching).
  2396                              <1> 	;	u.usp - points to kernel stack address which contains
  2397                              <1> 	;		user's registers while entering system call.  
  2398                              <1> 	;	u.sp  - points to kernel stack address 
  2399                              <1> 	;		to return from system call -for IRET-.
  2400                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2401                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2402                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2403                              <1> 	;
  2404                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2405                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2406                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2407                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2408                              <1> 	;	compatibles was using 1MB segmented memory 
  2409                              <1> 	;	in 8086/8088 times.
  2410                              <1> 	;
  2411                              <1> 	; INPUTS ->
  2412                              <1> 	;    r1 - process number of process to be read in
  2413                              <1> 	;    p.break - negative of word count of process 
  2414                              <1> 	;    p.dska - disk address of the process		
  2415                              <1> 	;    u.emt - determines handling of emt's 	
  2416                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2417                              <1> 	; OUTPUTS ->
  2418                              <1> 	;    8 = (u.ilgins)
  2419                              <1> 	;    24 = (u.emt)
  2420                              <1> 	;    swp - bit 10 is set to indicate read 
  2421                              <1> 	;		(bit 15=0 when reading is done)	
  2422                              <1> 	;    swp+2 - disk block address
  2423                              <1> 	;    swp+4 - negative word count 	
  2424                              <1> 	;      ((swp+6 - address of user structure)) 
  2425                              <1> 	;
  2426                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2427                              <1> 	;
  2428                              <1> 	; INPUTS ->
  2429                              <1> 	;    AL	- new process number (to be swapped in)	 
  2430                              <1> 	; OUTPUTS ->
  2431                              <1> 	;    none
  2432                              <1> 	;
  2433                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2434                              <1> 	;
  2435                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2436 00004EE4 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2437 00004EE6 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2438 00004EEB BF[A46E0000]        <1> 	mov	edi, user ; active user (u) structure	
  2439 00004EF0 F3A5                <1> 	rep	movsd
  2440 00004EF2 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2441 00004EF3 8B3D[A86E0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2442                              <1> 			     ;      points to user registers)
  2443 00004EF9 8B0D[A46E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2444                              <1> 			     ; (for IRET)
  2445                              <1> 			     ; [u.sp] -> EIP (user)
  2446                              <1> 			     ; [u.sp+4]-> CS (user)
  2447                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2448                              <1> 			     ; [u.sp+12] -> ESP (user)
  2449                              <1> 			     ; [u.sp+16] -> SS (user)		
  2450                              <1> 	; 28/08/2015
  2451 00004EFF 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2452 00004F01 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2453                              <1> 			     ; (for IRET) 	
  2454 00004F04 C1E902              <1> 	shr	ecx, 2	       		
  2455 00004F07 F3A5                <1> 	rep	movsd
  2456 00004F09 8B25[A86E0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2457 00004F0F 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2458 00004F10 C3                  <1> 	retn
  2459                              <1> 
  2460                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2461                              <1> 	;rswap:
  2462                              <1>        		; asl r1 / process number x2 for index
  2463                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2464                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2465                              <1>        		; bis $2000,swp / read
  2466                              <1>        		; jsr r0,ppoke / read it in 
  2467                              <1> 	; 1:
  2468                              <1>        		; tstb swp+1 / done
  2469                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2470                              <1>        		; mov u.emt,*$30 / yes move these
  2471                              <1>        		; mov u.ilgins,*$10 / back
  2472                              <1>        		; rts r0 / return
  2473                              <1> 
  2474                              <1> 	;unpack: ; / move stack back to its normal place
  2475                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2476                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2477                              <1> 		; blos 2f / yes, return
  2478                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2479                              <1> 			     ; / before swapping
  2480                              <1> 		; bhis 2f / yes, return
  2481                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2482                              <1> 		; add r3,r2
  2483                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2484                              <1> 	; 1:
  2485                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2486                              <1> 		; cmp r2,u.break / in core
  2487                              <1> 		; bne 1b
  2488                              <1> 	; 2:
  2489                              <1>        		; rts r0
  2490                              <1> 
  2491                              <1> putlu: 
  2492                              <1> 	; 12/09/2015
  2493                              <1> 	; 02/09/2015
  2494                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2495                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2496                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2497                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2498                              <1> 	; the last process on the queue to process in r1 by putting
  2499                              <1> 	; the process number in r1 into the last process's link.
  2500                              <1> 	;
  2501                              <1> 	; INPUTS ->
  2502                              <1> 	;    r1 - user process number
  2503                              <1> 	;    r2 - points to lowest priority queue 
  2504                              <1> 	;    p.dska - disk address of the process		
  2505                              <1> 	;    u.emt - determines handling of emt's 	
  2506                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2507                              <1> 	; OUTPUTS ->
  2508                              <1> 	;    r3 - process number of last process on the queue upon
  2509                              <1> 	;	  entering putlu
  2510                              <1> 	;    p.link-1 + r3 - process number in r1
  2511                              <1> 	;    r2 - points to lowest priority queue
  2512                              <1> 	;
  2513                              <1> 	; ((Modified registers: EDX, EBX)) 
  2514                              <1> 	;
  2515                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2516                              <1> 
  2517                              <1> 	; eBX = r2
  2518                              <1> 	; eAX = r1 (AL=r1b)
  2519                              <1> 
  2520 00004F11 BB[9C6E0000]        <1> 	mov	ebx, runq
  2521 00004F16 0FB613              <1> 	movzx  	edx, byte [ebx]
  2522 00004F19 43                  <1> 	inc	ebx
  2523 00004F1A 20D2                <1> 	and	dl, dl
  2524                              <1> 		; tstb (r2)+ / is queue empty?
  2525 00004F1C 740A                <1>        	jz	short putlu_1
  2526                              <1> 		; beq 1f / yes, branch
  2527 00004F1E 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2528                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2529                              <1> 			     ; / in r3
  2530 00004F20 8882[176C0000]      <1>        	mov	[edx+p.link-1], al
  2531                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2532                              <1> 			     ; / "last users" link
  2533 00004F26 EB03                <1> 	jmp	short putlu_2
  2534                              <1> 		; br 2f /
  2535                              <1> putlu_1: ; 1:
  2536 00004F28 8843FF              <1> 	mov	[ebx-1], al
  2537                              <1>        		; movb r1,-1(r2) / user is only user; 
  2538                              <1> 			    ; / put process no. at beginning and at end
  2539                              <1> putlu_2: ; 2: 
  2540 00004F2B 8803                <1> 	mov	[ebx], al
  2541                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2542                              <1> 			     ; / on the queue
  2543 00004F2D 88C2                <1> 	mov	dl, al
  2544 00004F2F 88B2[176C0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2545                              <1> 		; dec r2 / restore r2
  2546 00004F35 C3                  <1>         retn
  2547                              <1> 		; rts r0
  2548                              <1> 
  2549                              <1> ;copyz:
  2550                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2551                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2552                              <1> ;       mov     (r0)+,r1
  2553                              <1> ;       mov     (r0)+,r2
  2554                              <1> ;1:
  2555                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2556                              <1> ;       cmp     r1,r2 
  2557                              <1> ;       blo     1b
  2558                              <1> ;       mov     (sp)+,r2 / restore r2
  2559                              <1> ;       mov     (sp)+,r1 / restore r1
  2560                              <1> ;       rts     r0 
  2561                              <1> 
  2562                              <1> idle:
  2563                              <1> 	; 01/09/2015
  2564                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2565                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2566                              <1> 	; (idle & wait loop)
  2567                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2568                              <1> 	; idle procedure!
  2569                              <1>       	;
  2570                              <1>   	; 01/09/2015
  2571 00004F36 FB                  <1> 	sti
  2572                              <1>       	; 29/07/2013
  2573 00004F37 F4                  <1>       	hlt
  2574 00004F38 90                  <1>       	nop ; 10/10/2013
  2575 00004F39 90                  <1>       	nop
  2576 00004F3A 90                  <1>       	nop
  2577                              <1>       	; 23/10/2013
  2578 00004F3B 90                  <1>       	nop
  2579 00004F3C 90                  <1>       	nop
  2580 00004F3D 90                  <1>       	nop
  2581 00004F3E 90                  <1>       	nop
  2582 00004F3F C3                  <1>       	retn      
  2583                              <1> 
  2584                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2585                              <1> 	;clr *$ps / clear ps
  2586                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2587                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2588                              <1> 	;1 / wait for interrupt
  2589                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2590                              <1> 	;mov (sp)+,*$ps
  2591                              <1> 	;rts r0
  2592                              <1> 
  2593                              <1> clear:
  2594                              <1> 	; 03/02/2022
  2595                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2596                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2597                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2598                              <1> 	; on the current device (cdev)
  2599                              <1> 	;	
  2600                              <1> 	; INPUTS ->
  2601                              <1> 	;    r1 - block number of block to be zeroed
  2602                              <1> 	;    cdev - current device number 
  2603                              <1> 	; OUTPUTS ->
  2604                              <1> 	;    a zeroed I/O buffer onto the current device
  2605                              <1> 	;    r1 - points to last entry in the I/O buffer
  2606                              <1> 	;
  2607                              <1> 	; ((AX = R1)) input/output
  2608                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2609                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2610                              <1> 
  2611 00004F40 E8AB0D0000          <1> 	call 	wslot
  2612                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2613                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2614 00004F45 89DF                <1> 	mov	edi, ebx ; r5
  2615 00004F47 89C2                <1> 	mov	edx, eax
  2616 00004F49 B980000000          <1> 	mov	ecx, 128
  2617                              <1> 		; mov $256.,r3
  2618 00004F4E 31C0                <1> 	xor	eax, eax
  2619 00004F50 F3AB                <1> 	rep	stosd
  2620 00004F52 89D0                <1> 	mov	eax, edx
  2621                              <1> ; 1: 
  2622                              <1>        		; clr (r5)+ / zero data word in buffer
  2623                              <1>        		; dec r3
  2624                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2625                              <1> 	;call	dskwr
  2626                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2627                              <1>                              ; / block specified in r1
  2628                              <1> 	; eAX (r1) = block number
  2629                              <1> 	;retn
  2630                              <1> 		; rts r0
  2631                              <1> 	; 03/02/2022
  2632 00004F54 E9B30D0000          <1> 	jmp	dskwr
  2049                                  %include 'u4.s'        ; 15/04/2015
  2050                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2051                              <1> ; Last Modification: 26/02/2022
  2052                              <1> ; ----------------------------------------------------------------------------
  2053                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2054                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2055                              <1> ;
  2056                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2057                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2058                              <1> ; <Bell Laboratories (17/3/1972)>
  2059                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2060                              <1> ;
  2061                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2062                              <1> ;
  2063                              <1> ; ****************************************************************************
  2064                              <1> ; 14/10/2015
  2065                              <1> 
  2066                              <1> ;setisp:
  2067                              <1>        ;mov     r1,-(sp)
  2068                              <1>        ;mov     r2,-(sp)
  2069                              <1>        ;mov     r3,-(sp)
  2070                              <1>        ;mov     clockp,-(sp)
  2071                              <1>        ;mov     $s.syst+2,clockp
  2072                              <1>        ;jmp     (r0)
  2073                              <1> 
  2074                              <1> clock: ; / interrupt from 60 cycle clock
  2075                              <1> 	
  2076                              <1> 	; 14/10/2015
  2077                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2078                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2079                              <1> 
  2080                              <1>        ;mov     r0,-(sp) / save r0
  2081                              <1>        ;tst     *$lks / restart clock?
  2082                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2083                              <1>        ;inc     (r0)
  2084                              <1>        ;bne     1f
  2085                              <1>        ;inc     -(r0)
  2086                              <1> ;1:
  2087                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2088                              <1>        ;inc     (r0)
  2089                              <1>        ;bne     1f
  2090                              <1>        ;inc     -(r0)
  2091                              <1> ;1:
  2092                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2093                              <1> 
  2094 00004F59 803D[E86E0000]00    <1> 	cmp	byte [u.quant], 0
  2095 00004F60 772C                <1> 	ja	short clk_1
  2096                              <1> 	;
  2097 00004F62 803D[A16E0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2098 00004F69 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2099 00004F6B 803D[F56E0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2100 00004F72 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2101 00004F74 66833D[EA6E0000]00  <1> 	cmp	word [u.intr], 0
  2102 00004F7C 7616                <1> 	jna	short clk_2
  2103                              <1> clk_0:
  2104                              <1> 	; 14/10/2015
  2105 00004F7E FE05[A16E0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2106 00004F84 58                  <1> 	pop	eax ; return address to the timer interrupt
  2107                              <1> 	;
  2108 00004F85 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2109                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2110 00004F87 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2111                              <1> 	;
  2112 00004F89 E9D4EBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2113                              <1> clk_1:
  2114 00004F8E FE0D[E86E0000]      <1> 	dec	byte [u.quant]
  2115                              <1> clk_2:
  2116 00004F94 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2117                              <1> 
  2118                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2119                              <1> 
  2120                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2121                              <1>        ;decb    (r0)
  2122                              <1>        ;bge     1f / if less than 0
  2123                              <1>        ;clrb    (r0) / make it 0
  2124                              <1> ;1: / decrement time out counts return now if priority was not 0
  2125                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2126                              <1>        ;bge     2f / yes, check time outs
  2127                              <1>        ;tstb    (r0) / no, user timed out?
  2128                              <1>        ;bne     1f / no
  2129                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2130                              <1>        ;bne     1f / no, 1f
  2131                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2132                              <1>        ;sys     0 / sysrele
  2133                              <1>        ;rti
  2134                              <1> ;2: / priority is high so just decrement time out counts
  2135                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2136                              <1> ;2:
  2137                              <1>        ;tstb    (r0) / is the time out?
  2138                              <1>        ;beq     3f / yes, 3f (get next entry)
  2139                              <1>        ;decb    (r0) / no, decrement the time
  2140                              <1>        ;bne     3f / isit zero now?
  2141                              <1>        ;incb    (r0) / yes, increment the time
  2142                              <1> ;3:
  2143                              <1>        ;inc     r0 / next entry
  2144                              <1>        ;cmp     r0,$touts / end of toutt table?
  2145                              <1>        ;blo     2b / no, check this entry
  2146                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2147                              <1>        ;rti / return from interrupt
  2148                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2149                              <1>        ;mov     (sp)+,r0 / restore r0
  2150                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2151                              <1>        ;jsr     r0,setisp / save registers
  2152                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2153                              <1>                                ;  / the table
  2154                              <1> ;1:
  2155                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2156                              <1>        ;beq     2f / yes
  2157                              <1>        ;decb    toutt(r0) / no, decrement the time
  2158                              <1>        ;bne     2f / is the time 0, now
  2159                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2160                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2161                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2162                              <1> ;2:
  2163                              <1>        ;dec     r0 / set up r0 for next entry
  2164                              <1>        ;bge     1b / finished? , no, go back
  2165                              <1>        ;br      retisp / yes, restore registers and do a rti
  2166                              <1> 
  2167                              <1> ;retisp:
  2168                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2169                              <1>        ;mov     (sp)+,r3
  2170                              <1>        ;mov     (sp)+,r2
  2171                              <1>        ;mov     (sp)+,r1
  2172                              <1>        ;mov     (sp)+,r0
  2173                              <1>        ;rti     / return from interrupt
  2174                              <1> 
  2175                              <1> 
  2176                              <1> wakeup: ; / wakeup processes waiting for an event 
  2177                              <1> 	; / by linking them to the queue
  2178                              <1> 	;
  2179                              <1> 	; 26/02/2022
  2180                              <1> 	; 15/09/2015
  2181                              <1> 	; 29/06/2015
  2182                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2183                              <1> 	;
  2184                              <1> 	; 15/05/2013 - 02/06/2014
  2185                              <1> 	; Retro UNIX 8086 v1 modification !
  2186                              <1> 	; (Process/task switching routine by using
  2187                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2188                              <1> 	;
  2189                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2190                              <1> 	; sleeping in the specified wait channel by creating a link 
  2191                              <1> 	; to it from the last user process on the run queue.
  2192                              <1> 	; If there is no process to wake up, nothing happens.
  2193                              <1> 	;
  2194                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2195                              <1> 	; 'switching' status of the current process (owns current tty)
  2196                              <1> 	; (via alt + function keys) to a process which has highest
  2197                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2198                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2199                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2200                              <1> 	; tty for tty switching by keyboard.)	 
  2201                              <1> 	; 
  2202                              <1> 	; INPUT -> 
  2203                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2204                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2205                              <1> 	;
  2206                              <1> 	; ((modified registers: EAX, EBX))
  2207                              <1> 	;
  2208 00004F95 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2209 00004F98 81C3[486B0000]      <1> 	add	ebx, wlist
  2210 00004F9E 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2211 00004FA0 20C0                <1> 	and	al, al
  2212 00004FA2 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2213                              <1> 	;
  2214 00004FA4 30E4                <1> 	xor	ah, ah
  2215 00004FA6 8825[E86E0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2216 00004FAC 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2217                              <1> 	; 15/09/2015
  2218 00004FAE 0FB6D8              <1> 	movzx	ebx, al
  2219                              <1> 	; 26/02/2022 (p.waitc is not used)
  2220                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2221 00004FB1 FEC4                <1> 	inc	ah
  2222 00004FB3 88A3[276C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2223                              <1> 	;
  2224 00004FB9 57                  <1> 	push	edi
  2225 00004FBA 52                  <1> 	push	edx
  2226 00004FBB E851FFFFFF          <1> 	call	putlu
  2227 00004FC0 5A                  <1> 	pop	edx
  2228 00004FC1 5F                  <1> 	pop	edi
  2229                              <1> wa0:
  2230 00004FC2 C3                  <1> 	retn
  2231                              <1> 
  2232                              <1> sleep: 
  2233                              <1> 	; 26/02/2022
  2234                              <1> 	; 03/02/2022
  2235                              <1> 	; 15/09/2015
  2236                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2237                              <1> 	;
  2238                              <1> 	; 09/05/2013 - 20/03/2014
  2239                              <1> 	;
  2240                              <1> 	; Retro UNIX 8086 v1 modification !
  2241                              <1> 	; (Process/task switching and quit routine by using
  2242                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2243                              <1> 	;
  2244                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2245                              <1> 	; tty and tape output or input becomes available
  2246                              <1> 	; and process is put on waiting channel and swapped out,
  2247                              <1> 	; then -when the tty or tape is ready to write or read-
  2248                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2249                              <1> 	;
  2250                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2251                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2252                              <1> 	; status of the current process also INT 1Ch will count down
  2253                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2254                              <1> 	; to tty buffer of the current process and kernel will get
  2255                              <1> 	; user input by using tty buffer of the current process
  2256                              <1> 	; (instead of standard INT 16h interrupt).
  2257                              <1> 	; TTY output will be redirected to related video page of text mode
  2258                              <1> 	; (INT 10h will be called with different video page depending
  2259                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2260                              <1> 	; pseudo screens.)
  2261                              <1> 	;
  2262                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2263                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2264                              <1> 	; characters/data on serial port(s).
  2265                              <1> 	;
  2266                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2267                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2268                              <1> 	; 
  2269                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2270                              <1> 	;
  2271                              <1> 	;; 05/10/2013
  2272                              <1>         ;10/12/2013
  2273                              <1> 	;cmp   byte [u.uno], 1
  2274                              <1>         ;ja    short sleep0
  2275                              <1> 	;retn
  2276                              <1> 
  2277                              <1> 	; 20/03/2014
  2278                              <1> 	;mov	bx, [runq]
  2279                              <1> 	;cmp	bl, bh
  2280                              <1> 	;jne	short sleep0	
  2281                              <1> 	; 25/02/2014
  2282                              <1> 	;cmp word ptr [runq], 0
  2283                              <1> 	;ja short sleep0	
  2284                              <1> 	;retn
  2285                              <1> sleep0:
  2286                              <1> 	;
  2287 00004FC3 E849000000          <1> 	call	isintr
  2288                              <1> 	;jnz	sysret
  2289                              <1> 		; / wait for event
  2290                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2291                              <1> 			      ; / or quit from user
  2292                              <1>                		; br 2f / something happened
  2293                              <1> 			      ; / yes, his interrupt so return
  2294                              <1>                      	      ;	/ to user
  2295                              <1> 	; 03/02/2022
  2296 00004FC8 7405                <1> 	jz	short sleep_2
  2297                              <1> sleep_3:
  2298 00004FCA E937EBFFFF          <1> 	jmp	sysret
  2299                              <1> sleep_2:
  2300                              <1> 	; 30/06/2015
  2301 00004FCF 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2302 00004FD2 81C3[486B0000]      <1> 	add	ebx, wlist
  2303 00004FD8 8A03                <1> 	mov	al, [ebx]
  2304 00004FDA 20C0                <1> 	and	al, al
  2305 00004FDC 7407                <1> 	jz	short sleep1
  2306 00004FDE 53                  <1> 	push	ebx
  2307 00004FDF E82DFFFFFF          <1> 	call	putlu
  2308 00004FE4 5B                  <1> 	pop	ebx
  2309                              <1> sleep1:
  2310 00004FE5 A0[F56E0000]        <1> 	mov	al, [u.uno]    
  2311 00004FEA 8803                <1>   	mov	[ebx], al 	; put the process number
  2312                              <1> 				; in the wait channel
  2313                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2314                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2315                              <1> 				     ; / on the stack
  2316                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2317                              <1> 				     ; / to put to sleep in there
  2318                              <1>         ; 15/09/2015
  2319 00004FEC 0FB6D8              <1> 	movzx	ebx, al
  2320 00004FEF C683[276C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2321                              <1> 	; 26/02/2022 (p.waitc is not used)
  2322                              <1> 	;inc	ah
  2323                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2324                              <1> 	;
  2325 00004FF6 66FF35[906E0000]    <1> 	push    word [cdev]
  2326                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2327 00004FFD E842FEFFFF          <1> 	call	swap
  2328                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2329 00005002 668F05[906E0000]    <1>         pop     word [cdev]
  2330                              <1> 		; mov (sp)+,cdev / restore device
  2331 00005009 E803000000          <1> 	call	isintr
  2332                              <1> 	; 22/09/2013
  2333                              <1> 	;jnz	sysret         
  2334                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2335                              <1>                		; br 2f / yes, return to new user
  2336                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2337                              <1> 				; / originally on the wait channel
  2338                              <1>        		; beq 1f / if 0 branch
  2339                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2340                              <1>        		; mov $300,*$ps / processor priority = 6
  2341                              <1> 		; jsr r0,putlu / create link to old process number
  2342                              <1>        		; clr *$ps / clear the status; process priority = 0
  2343                              <1> 	; 03/02/2022
  2344 0000500E 75BA                <1> 	jnz	short sleep_3
  2345                              <1>      ;1:
  2346 00005010 C3                  <1> 	retn
  2347                              <1> 		; rts r0 / return
  2348                              <1>      ;2:
  2349                              <1>         ;;jmp	sysret
  2350                              <1> 		; jmp sysret / return to user
  2351                              <1> 
  2352                              <1> isintr:
  2353                              <1> 	; 03/02/2022
  2354                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2355                              <1> 	;
  2356                              <1> 	; 09/05/2013 - 30/05/2014
  2357                              <1> 	;
  2358                              <1> 	; Retro UNIX 8086 v1 modification !
  2359                              <1> 	; (Process/task switching and quit routine by using
  2360                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2361                              <1> 	;
  2362                              <1> 	; Retro UNIX 8086 v1 modification:
  2363                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2364                              <1> 	;  and there is a 'quit' request by user;
  2365                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2366                              <1> 	;  "nothing to do". (20/10/2013)
  2367                              <1> 	;
  2368                              <1> 	; 20/10/2013
  2369 00005011 66833D[DC6E0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2370 00005019 761F                <1> 	jna	short isintr2 ; retn
  2371                              <1> 	; 03/09/2013
  2372                              <1> 	; (nothing to do)
  2373                              <1> 	;retn
  2374                              <1> 	; 22/09/2013
  2375 0000501B 66833D[EA6E0000]00  <1> 	cmp	word [u.intr], 0
  2376 00005023 7615                <1> 	jna	short isintr2 ; retn
  2377                              <1> 	; 30/05/2014
  2378                              <1> 	;push	ax
  2379                              <1> 	; 03/02/2022
  2380 00005025 50                  <1> 	push	eax
  2381 00005026 66A1[EC6E0000]      <1> 	mov	ax, [u.quit]
  2382 0000502C 6609C0              <1> 	or	ax, ax ; 0 ?
  2383 0000502F 7408                <1> 	jz	short isintr1 ; zf = 1
  2384 00005031 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2385 00005035 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2386                              <1> 	;xor	ax, ax ; zf = 1
  2387                              <1> 	; 03/02/2022
  2388 00005037 31C0                <1> 	xor	eax, eax ; zf = 1
  2389                              <1> isintr1:
  2390                              <1> 	;pop	ax
  2391                              <1> 	; 03/02/2022
  2392 00005039 58                  <1> 	pop	eax
  2393                              <1> isintr2: ; 22/09/2013
  2394                              <1> 	; zf=1 -> nothing to do
  2395 0000503A C3                  <1> 	retn
  2396                              <1> 
  2397                              <1> 	; UNIX v1 original 'isintr' routine... 
  2398                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2399                              <1>        	;mov     r2,-(sp) / save r2
  2400                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2401                              <1>         ;                 / typewriter
  2402                              <1>        	;beq     1f / if 0, do nothing except skip return
  2403                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2404                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2405                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2406                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2407                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2408                              <1>         ;              / of interrupts
  2409                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2410                              <1>      ;1:
  2411                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2412                              <1>      ;4:
  2413                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2414                              <1>        	;mov     (sp)+,r1
  2415                              <1>        	;rts     r0
  2416                              <1>      ;3: / interrupt char = quit (fs)
  2417                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2418                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2419                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2420                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2421                              <1>      ;1: / find process control tty entry in tty block
  2422                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2423                              <1>        	;beq     1f / block found go to 1f
  2424                              <1>        	;add     $8,r1 / look at next tty block
  2425                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2426                              <1>        	;blo     1b / no
  2427                              <1>        	;br      4b / no process control tty found so go to 4b
  2428                              <1>      ;1:
  2429                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2430                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2431                              <1>         ;                  / identifier
  2432                              <1>        	;inc     0f / increment
  2433                              <1>      ;1:
  2434                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2435                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2436                              <1>         ;             / being typed out after you hit the interrupt
  2437                              <1>         ;             / key
  2438                              <1>        	;br      1b
  2050                                  %include 'u5.s'        ; 03/06/2015
  2051                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2052                              <1> ; Last Modification: 12/02/2022
  2053                              <1> ; ----------------------------------------------------------------------------
  2054                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2055                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2056                              <1> ;
  2057                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2058                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2059                              <1> ; <Bell Laboratories (17/3/1972)>
  2060                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2061                              <1> ;
  2062                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2063                              <1> ;
  2064                              <1> ; ****************************************************************************
  2065                              <1> ; 14/11/2015
  2066                              <1> 
  2067                              <1> mget:
  2068                              <1> 	; 03/02/2022
  2069                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2070                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2071                              <1> 	;
  2072                              <1> 	; Get existing or (allocate) a new disk block for file
  2073                              <1> 	; 
  2074                              <1> 	; INPUTS ->
  2075                              <1> 	;    u.fofp (file offset pointer)
  2076                              <1> 	;    inode 
  2077                              <1> 	;    u.off (file offset)
  2078                              <1> 	; OUTPUTS ->
  2079                              <1> 	;    r1 (physical block number)
  2080                              <1> 	;    r2, r3, r5 (internal)
  2081                              <1> 	;
  2082                              <1> 	; ((AX = R1)) output
  2083                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2084                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2085                              <1> 
  2086                              <1> 		; mov *u.fofp,mq / file offset in mq
  2087                              <1> 		; clr ac / later to be high sig
  2088                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2089                              <1> 		; mov mq,r2
  2090                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2091                              <1> 		; bne 4f / branch for large file
  2092                              <1> mget_0:	
  2093                              <1> 	; 03/02/2022
  2094 0000503B 29C0                <1> 	sub	eax, eax
  2095 0000503D 29D2                <1> 	sub	edx, edx
  2096 0000503F 29C9                <1> 	sub	ecx, ecx
  2097 00005041 29DB                <1> 	sub	ebx, ebx
  2098                              <1> 
  2099 00005043 8B35[BC6E0000]      <1>         mov     esi, [u.fofp]
  2100                              <1>         ;movzx	ebx, byte [esi+1]
  2101                              <1> 	; 03/02/2022
  2102 00005049 46                  <1> 	inc	esi
  2103 0000504A 8A1E                <1> 	mov	bl, [esi]
  2104                              <1> 
  2105                              <1> 	; BX = r2
  2106                              <1> 	; 03/02/2022
  2107 0000504C F605[A96B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2108                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2109                              <1> 			  	     ; is this a large or small file
  2110 00005053 756A                <1> 	jnz 	short mget_5 ; 4f ; large file
  2111                              <1> 
  2112 00005055 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2113                              <1> 		; bit $!17,r2
  2114 00005058 7525                <1> 	jnz 	short mget_2
  2115                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2116 0000505A 80E30E              <1>         and     bl, 0Eh  
  2117                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2118                              <1> 	; 03/02/2022
  2119 0000505D 668B83[AE6B0000]    <1> 	mov	ax, [ebx+i.dskp]
  2120                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2121                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2122                              <1> 	; 03/02/2022
  2123 00005064 09C0                <1> 	or	eax, eax
  2124                              <1> 	;or 	ax, ax
  2125 00005066 7516                <1> 	jnz 	short mget_1 
  2126                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2127                              <1> 		       ; / for file
  2128 00005068 E8A4000000          <1> 	call 	alloc
  2129                              <1> 		; jsr r0,alloc / allocate a new block
  2130                              <1>          ; eAX (r1) = Physical block number
  2131 0000506D 668983[AE6B0000]    <1> 	mov 	[ebx+i.dskp], ax
  2132                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2133 00005074 E833020000          <1> 	call 	setimod	
  2134                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2135 00005079 E8C2FEFFFF          <1> 	call	clear
  2136                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2137                              <1> mget_1: ; 2:
  2138                              <1>         ; eAX (r1) = Physical block number
  2139 0000507E C3                  <1> 	retn 
  2140                              <1> 		; rts r0
  2141                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2142 0000507F E88D000000          <1> 	call 	alloc
  2143                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2144                              <1> 	                     ; / block number in r1
  2145                              <1>         ; eAX (r1) = Physical block number
  2146 00005084 E8670C0000          <1> 	call 	wslot
  2147                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2148                              <1> 			     ; / first data word in buffer
  2149                              <1>         ; 03/02/2022
  2150 00005089 31C9                <1> 	xor	ecx, ecx
  2151 0000508B B108                <1> 	mov	cl, 8
  2152                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2153                              <1> 		   ; into new indirect block area for the new
  2154                              <1> 		   ; large file		
  2155 0000508D 89DF                <1> 	mov 	edi, ebx ; r5
  2156 0000508F BE[AE6B0000]        <1> 	mov 	esi, i.dskp 
  2157                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2158                              <1> 			   ; / block pointers
  2159                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2160                              <1> 			  ; / large file
  2161                              <1> 	;xor 	ax, ax ; mov ax, 0
  2162                              <1> 	; 03/02/2022
  2163 00005094 31C0                <1> 	xor	eax, eax
  2164                              <1> mget_3: ;1:
  2165 00005096 66A5                <1> 	movsw
  2166                              <1> 		; mov (r2),(r5)+
  2167 00005098 668946FE            <1> 	mov 	[esi-2], ax
  2168                              <1> 		; clr (r2)+
  2169 0000509C E2F8                <1> 	loop	mget_3 ; 1b
  2170                              <1> 		; dec r3
  2171                              <1> 		; bgt 1b
  2172                              <1> 
  2173 0000509E B1F8                <1> 	mov 	cl, 256-8
  2174                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2175                              <1> mget_4:	; 1
  2176 000050A0 F366AB              <1> 	rep 	stosw
  2177                              <1> 		; clr (r5)+
  2178                              <1> 		; dec r3
  2179                              <1> 		; bgt 1b
  2180                              <1> 	; 24/03/2013
  2181                              <1>         ; AX (r1) = Physical block number
  2182 000050A3 E8640C0000          <1> 	call	dskwr
  2183                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2184                              <1>         ; eAX (r1) = Physical block number
  2185 000050A8 66A3[AE6B0000]      <1> 	mov 	[i.dskp], ax
  2186                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2187                              <1> 	; 03/02/2022
  2188 000050AE 800D[A96B0000]10    <1> 	or	byte [i.flgs+1], 10h
  2189                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2190                              <1> 		; bis $10000,i.flgs / set large file bit 
  2191                              <1> 				  ; / in i.flgs word of i-node
  2192 000050B5 E8F2010000          <1> 	call	setimod
  2193                              <1> 		; jsr r0,setimod / set i-node modified flag
  2194 000050BA E97CFFFFFF          <1>         jmp     mget_0 
  2195                              <1> 		; br mget
  2196                              <1> 
  2197                              <1> mget_5:  ; 4 ; large file
  2198                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2199                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2200                              <1> 			    ; / in indirect block
  2201                              <1> 		; mov r2,-(sp) / save on stack (*)
  2202                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2203                              <1>        		          ; / indirect block
  2204                              <1> 		; bic $!16,r2
  2205 000050BF 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2206 000050C2 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2207                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2208                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2209                              <1> 	; There is always 1 indirect block for this file system
  2210                              <1> 	; 03/02/2022
  2211 000050C3 66A1[AE6B0000]      <1> 	mov	ax, [i.dskp]
  2212                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2213                              <1> 		; mov i.dskp(r2),r1
  2214                              <1> 	; 03/02/2022
  2215 000050C9 09C0                <1> 	or	eax, eax
  2216                              <1> 	;or 	ax, ax ; R1
  2217 000050CB 7515                <1> 	jnz 	short mget_6 ; 2f
  2218                              <1> 		; bne 2f / if no indirect block exists
  2219 000050CD E83F000000          <1> 	call 	alloc
  2220                              <1> 		; jsr r0,alloc / allocate a new block
  2221 000050D2 66A3[AE6B0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2222                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2223 000050D8 E8CF010000          <1> 	call 	setimod
  2224                              <1> 		; jsr r0,setimod / set i-node modified byte
  2225                              <1> 	; eAX = new block number
  2226 000050DD E85EFEFFFF          <1> 	call 	clear
  2227                              <1> 		; jsr r0,clear / clear new block
  2228                              <1> mget_6: ;2
  2229                              <1> 	; 05/03/2013
  2230                              <1> 	; eAX = r1, physical block number (of indirect block)
  2231 000050E2 E8970B0000          <1> 	call 	dskrd ; read indirect block
  2232                              <1> 		; jsr r0,dskrd / read in indirect block
  2233 000050E7 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2234                              <1> 		; mov (sp)+,r2 / get offset
  2235                              <1> 	; eAX = r1, physical block number (of indirect block)
  2236 000050E8 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2237                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2238                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2239 000050E9 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2240                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2241                              <1> 	                  ; / points to location of inter
  2242                              <1> 	; 03/02/2022
  2243 000050EB 668B03              <1> 	mov	ax, [ebx]
  2244                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2245                              <1> 			      ; in file sought in R1 (AX)
  2246                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2247                              <1> 	               	    ; / sought in r1
  2248                              <1> 	; 03/02/2022
  2249 000050EE 09C0                <1> 	or	eax, eax
  2250                              <1> 	;or 	ax, ax
  2251 000050F0 751D                <1>         jnz 	short mget_7 ; 2f
  2252                              <1> 		; bne 2f / if no block exists 
  2253 000050F2 E81A000000          <1> 	call 	alloc
  2254                              <1> 		; jsr r0,alloc / allocate a new block
  2255 000050F7 668903              <1> 	mov 	[ebx], ax ; R1
  2256                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2257                              <1> 	                    ; / indirect block
  2258 000050FA 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2259                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2260 000050FB 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2261 000050FC 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2262 000050FD 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2263                              <1> 		; mov (r2),-(sp) / save block number of new block
  2264                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2265 000050FF E8EC0B0000          <1> 	call 	wslot
  2266                              <1> 		; jsr r0,wslot
  2267                              <1>         ; eAX (r1) = physical block number
  2268                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2269 00005104 E8030C0000          <1> 	call 	dskwr
  2270                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2271                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2272                              <1> 			     ; / back out on disk
  2273 00005109 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2274                              <1> 		; mov (sp),r1 / restore block number of new block	
  2275                              <1> 	; eAX (r1) = physical block number of new block
  2276 0000510A E831FEFFFF          <1> 	call 	clear
  2277                              <1> 		; jsr r0,clear / clear new block	
  2278                              <1> mget_7: ; 2
  2279 0000510F 5A                  <1> 	pop 	edx ; **
  2280                              <1> 		; tst (sp)+ / bump stack pointer
  2281                              <1> 	; eAX (r1) = Block number of new block
  2282 00005110 C3                  <1> 	retn
  2283                              <1> 		; rts r0
  2284                              <1> 
  2285                              <1> alloc:
  2286                              <1> 	; 03/02/2022
  2287                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2288                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2289                              <1> 	;
  2290                              <1> 	; get a free block and 
  2291                              <1> 	; set the corresponding bit in the free storage map
  2292                              <1> 	; 
  2293                              <1> 	; INPUTS ->
  2294                              <1> 	;    cdev (current device)
  2295                              <1> 	;    r2 
  2296                              <1> 	;    r3
  2297                              <1> 	; OUTPUTS ->
  2298                              <1> 	;    r1 (physical block number of block assigned)
  2299                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2300                              <1> 	;
  2301                              <1> 	; ((AX = R1)) output
  2302                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2303                              <1>         ;    ((Modified registers: DX, CX))  
  2304                              <1> 
  2305                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2306                              <1> 		;mov r3,-(sp)
  2307                              <1> 	;push 	ecx
  2308 00005111 53                  <1> 	push 	ebx ; R2
  2309                              <1> 	;push 	edx ; R3
  2310 00005112 BB[647B0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2311                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2312 00005117 803D[906E0000]00    <1> 	cmp 	byte [cdev], 0
  2313                              <1> 		; tst cdev
  2314 0000511E 7605                <1> 	jna	short alloc_1
  2315                              <1> 		; beq 1f / drum is device
  2316 00005120 BB[6C7D0000]        <1> 	mov	ebx, mount
  2317                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2318                              <1> 			      ; / free storage map
  2319                              <1> alloc_1: ; 1
  2320                              <1> 	; 03/02/2022
  2321                              <1> 	;sub	ecx, ecx
  2322                              <1> 	;sub	edx, edx
  2323                              <1> 	;sub	eax, eax
  2324                              <1> 
  2325 00005125 668B0B              <1>         mov	cx, [ebx]
  2326                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2327                              <1> 			     ; / storage map
  2328                              <1> 	; 03/02/2022
  2329 00005128 C1E103              <1> 	shl	ecx, 3
  2330                              <1> 	;shl	cx, 3
  2331                              <1> 		; asl r1 / multiply r1 by eight gives 
  2332                              <1> 		; number of blocks in device
  2333                              <1> 		; asl r1
  2334                              <1> 		; asl r1
  2335                              <1> 	;;push	cx ;; 01/08/2013
  2336                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2337 0000512B 31C0                <1> 	xor 	eax, eax ; 0
  2338                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2339                              <1> alloc_2: ; 1
  2340 0000512D 43                  <1> 	inc 	ebx ; 18/8/2012
  2341 0000512E 43                  <1> 	inc 	ebx ; 
  2342 0000512F 668B13              <1> 	mov 	dx, [ebx]
  2343                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2344                              <1> 	; 03/02/2022
  2345 00005132 09D2                <1> 	or	edx, edx
  2346                              <1> 	;or 	dx, dx
  2347 00005134 750D                <1> 	jnz 	short alloc_3 ; 1f
  2348                              <1> 		; bne 1f / branch if any free blocks in this word	
  2349 00005136 6683C010            <1> 	add 	ax, 16
  2350                              <1> 		; add $16.,r1
  2351                              <1> 	; 03/02/2022
  2352 0000513A 39C8                <1> 	cmp	eax, ecx
  2353                              <1> 	;cmp 	ax, cx    
  2354                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2355 0000513C 72EF                <1> 	jb 	short alloc_2
  2356                              <1> 		; blo 1b
  2357                              <1> 	; 14/11/2015
  2358                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2359                              <1> 	;	because of a (DMA or another) r/w error, 
  2360                              <1> 	;	we will be here, at 'jmp panic' code address,
  2361                              <1> 	;	even if the (disk) file system space is not full !!!
  2362                              <1> 	;	(cx = 0)	
  2363                              <1> 	;
  2364 0000513E E957E2FFFF          <1> 	jmp     panic 
  2365                              <1> 		; jmp panic / found no free storage
  2366                              <1> alloc_3: ; 1
  2367                              <1> 	; 03/02/2022
  2368 00005143 D1EA                <1> 	shr	edx, 1
  2369                              <1> 	;shr	dx, 1
  2370                              <1> 		; asr r3 / find a free block
  2371 00005145 7203                <1> 	jc	short alloc_4 ; 1f
  2372                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2373                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2374                              <1> 	; 03/02/2022
  2375 00005147 40                  <1> 	inc	eax
  2376                              <1> 	;inc	ax
  2377                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2378 00005148 EBF9                <1> 	jmp 	short alloc_3
  2379                              <1> 		; br 1b
  2380                              <1> alloc_4: ; 1:
  2381                              <1> 	;; pop cx ;; 01/08/2013
  2382                              <1> 		; tst (sp)+ / bump sp
  2383                              <1> 	; 02/04/2013 
  2384 0000514A E829000000          <1> 	call	free3
  2385                              <1> 		; jsr r0,3f / have found a free block
  2386                              <1> 	; 21/8/2012
  2387 0000514F 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2388 00005152 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2389                              <1> 		; bic r3,(r2) / set bit for this block 
  2390                              <1> 		            ; / i.e. assign block
  2391                              <1> 		; br 2f
  2392 00005155 EB09                <1> 	jmp 	short alloc_5
  2393                              <1> 
  2394                              <1> free:
  2395                              <1> 	; 03/02/2022
  2396                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2397                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2398                              <1> 	;
  2399                              <1> 	; calculates byte address and bit position for given block number
  2400                              <1> 	; then sets the corresponding bit in the free storage map
  2401                              <1> 	; 
  2402                              <1> 	; INPUTS ->
  2403                              <1> 	;    r1 - block number for a block structured device
  2404                              <1> 	;    cdev - current device 
  2405                              <1> 	; OUTPUTS ->
  2406                              <1> 	;    free storage map is updated
  2407                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2408                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2409                              <1> 	;
  2410                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2411                              <1>         ;  ((Modified registers: DX, CX))  
  2412                              <1> 
  2413                              <1> 		;mov r2,-(sp) / save r2, r3
  2414                              <1> 		;mov r3,-(sp)
  2415                              <1> 	;push 	ecx
  2416 00005157 53                  <1> 	push 	ebx ; R2
  2417                              <1> 	;push 	edx ; R3 
  2418                              <1> 
  2419 00005158 E81B000000          <1>         call    free3
  2420                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2421                              <1> 				 ; / in free storage map for block
  2422 0000515D 660913              <1> 	or 	[ebx], dx  
  2423                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2424                              <1> 			    ;  / indicates free block	
  2425                              <1> 	; 0 -> allocated, 1 -> free
  2426                              <1> 
  2427                              <1> alloc_5:
  2428                              <1> 	; 07/04/2013
  2429                              <1> free_1: ; 2:
  2430                              <1> 	;pop 	edx
  2431                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2432 00005160 5B                  <1> 	pop	ebx
  2433                              <1> 		; mov (sp)+,r2
  2434                              <1> 	; pop	ecx
  2435 00005161 803D[906E0000]00    <1> 	cmp 	byte [cdev], 0
  2436                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2437                              <1> 			 ; / cdev = 1, mountable device
  2438 00005168 7707                <1> 	ja	short alloc_6 ; 1f
  2439                              <1> 		; bne 1f
  2440                              <1> 	;mov	byte [smod], 1
  2441 0000516A FE05[9F6E0000]      <1> 	inc 	byte [smod]
  2442                              <1> 		; incb smod / set super block modified for drum
  2443                              <1> 	; eAX (r1) = block number
  2444 00005170 C3                  <1> 	retn
  2445                              <1> 		; rts r0
  2446                              <1> free_2:
  2447                              <1> alloc_6: ; 1:
  2448                              <1> 	;mov 	byte [mmod], 1
  2449 00005171 FE05[A06E0000]      <1> 	inc 	byte [mmod]
  2450                              <1> 		; incb	mmod 
  2451                              <1> 		  ; / set super block modified for mountable device
  2452                              <1> 	; eAX (r1) = block number
  2453 00005177 C3                  <1> 	retn	
  2454                              <1> 		; rts r0
  2455                              <1> free3:
  2456                              <1> 	; 03/02/2022
  2457                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2458                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2459                              <1> 	;
  2460                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2461                              <1> 	; 
  2462                              <1> alloc_free_3: ; 3
  2463                              <1> 	;mov 	dx, 1
  2464                              <1> 	; 03/02/2022
  2465 00005178 31D2                <1> 	xor	edx, edx
  2466 0000517A 42                  <1> 	inc	edx
  2467                              <1> 	; edx = 1
  2468 0000517B 88C1                <1> 	mov 	cl, al
  2469                              <1> 		; mov r1,r2 / block number, k, = 1		
  2470 0000517D 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2471                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2472 00005180 7402                <1> 	jz 	short free4
  2473                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2474                              <1> 			       ; / (k) mod 8
  2475                              <1> 	;shl 	dx, cl
  2476                              <1> 	; 03/02/2022
  2477 00005182 D3E2                <1> 	shl	edx, cl
  2478                              <1> free4:
  2479 00005184 0FB7D8              <1> 	movzx 	ebx, ax
  2480                              <1> 		; mov r1,r2 / divide block number by 16
  2481                              <1> 	; 03/02/2022
  2482 00005187 C1EB04              <1> 	shr	ebx, 4
  2483                              <1> 	;shr 	bx, 4
  2484                              <1> 		; asr r2
  2485                              <1> 		; asr r2
  2486                              <1> 		; asr r2
  2487                              <1> 		; asr r2
  2488                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2489                              <1> 		       ; / bit for block is in lower half of word
  2490                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2491                              <1> 		        ; / storage map
  2492                              <1> alloc_free_4: ; 1
  2493                              <1> 	; 03/02/2022
  2494 0000518A D1E3                <1> 	shl	ebx, 1
  2495                              <1> 	;shl 	bx, 1
  2496                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2497 0000518C 81C3[667B0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2498                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2499                              <1> 	    		        ; / with block bit in it 	
  2500 00005192 803D[906E0000]00    <1> 	cmp	byte [cdev], 0
  2501                              <1> 		; tst cdev
  2502 00005199 7606                <1> 	jna	short alloc_free_5
  2503                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2504 0000519B 81C308020000        <1> 	add	ebx, mount - systm
  2505                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2506                              <1> 				    ; / mountable device with bit of block to be
  2507                              <1> 				    ; / freed
  2508                              <1> alloc_free_5: ; 1 
  2509 000051A1 C3                  <1> 	retn
  2510                              <1> 		; rts r0 / return to 'free'
  2511                              <1> 	      ; 2
  2512                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2513                              <1> 	
  2514                              <1> iget:
  2515                              <1> 	; 03/02/2022
  2516                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2517                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2518                              <1> 	;
  2519                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2520                              <1> 	;
  2521                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2522                              <1> 	; 
  2523                              <1> 	; INPUTS ->
  2524                              <1> 	;    ii - current i-number, rootdir
  2525                              <1> 	;    cdev - new i-node device
  2526                              <1> 	;    idev - current i-node device
  2527                              <1> 	;    imod - current i-node modified flag
  2528                              <1> 	;    mnti - cross device file i-number
  2529                              <1> 	;    r1 - i-numbe rof new i-node
  2530                              <1> 	;    mntd - mountable device number		
  2531                              <1> 	; 	 
  2532                              <1> 	; OUTPUTS ->
  2533                              <1> 	;    cdev, idev, imod, ii, r1
  2534                              <1> 	;
  2535                              <1> 	; ((AX = R1)) input/output
  2536                              <1> 	;
  2537                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2538                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2539                              <1> 
  2540 000051A2 8A15[906E0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2541 000051A8 8A35[8E6E0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2542                              <1> 	;
  2543 000051AE 663B05[8C6E0000]    <1> 	cmp 	ax, [ii]
  2544                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2545 000051B5 7504                <1> 	jne 	short iget_1
  2546                              <1> 		; bne 1f
  2547 000051B7 38F2                <1> 	cmp	dl, dh
  2548                              <1> 		; cmp idev,cdev
  2549                              <1> 			  ; / is device number of i-node = current device
  2550 000051B9 7472                <1>         je      short iget_5
  2551                              <1> 		; beq 2f
  2552                              <1> iget_1: ; 1:
  2553 000051BB 30DB                <1> 	xor	bl, bl
  2554 000051BD 381D[9E6E0000]      <1> 	cmp	[imod], bl ; 0	
  2555                              <1> 		; tstb imod / has i-node of current file
  2556                              <1> 			  ; / been modified i.e., imod set
  2557 000051C3 7629                <1> 	jna	short iget_2
  2558                              <1> 		; beq 1f
  2559 000051C5 881D[9E6E0000]      <1> 	mov	[imod], bl ; 0
  2560                              <1> 		;  clrb	imod / if it has, 
  2561                              <1> 			   ; / we must write the new i-node out on disk
  2562                              <1> 	; 03/02/2022
  2563 000051CB 50                  <1> 	push	eax ; *
  2564                              <1> 	;push	ax
  2565                              <1> 		; mov r1,-(sp)
  2566                              <1> 	;mov	dl, [cdev]
  2567 000051CC 52                  <1> 	push	edx ; **
  2568                              <1> 	;push	dx
  2569                              <1> 		; mov cdev,-(sp)
  2570 000051CD 66A1[8C6E0000]      <1> 	mov	ax, [ii]
  2571                              <1> 		; mov ii,r1
  2572                              <1> 	;mov	dh, [idev]
  2573 000051D3 8835[906E0000]      <1> 	mov	[cdev], dh
  2574                              <1> 		; mov idev,cdev
  2575 000051D9 FEC3                <1> 	inc	bl ; 1
  2576                              <1> 	; 31/07/2013
  2577 000051DB 881D[286F0000]      <1> 	mov     [rw], bl ; 1 == write 
  2578                              <1> 	;;28/07/2013 rw -> u.rw
  2579                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2580 000051E1 E848000000          <1> 	call	icalc
  2581                              <1> 		; jsr r0,icalc; 1
  2582                              <1> 	;pop	dx
  2583                              <1> 	; 03/02/2022
  2584 000051E6 5A                  <1> 	pop	edx ; **
  2585 000051E7 8815[906E0000]      <1> 	mov	[cdev], dl
  2586                              <1> 		; mov (sp)+,cdev
  2587                              <1> 	; 03/02/2022
  2588 000051ED 58                  <1> 	pop	eax ; *
  2589                              <1> 	;pop	ax
  2590                              <1> 		; mov (sp)+,r1
  2591                              <1> iget_2: ; 1:
  2592 000051EE 6621C0              <1> 	and	ax, ax
  2593                              <1> 		; tst r1 / is new i-number non zero
  2594 000051F1 7434                <1> 	jz	short iget_4 ; 2f
  2595                              <1> 		; beq 2f / branch if r1=0
  2596                              <1> 
  2597                              <1> 	;mov 	dl, [cdev]
  2598 000051F3 08D2                <1> 	or	dl, dl
  2599                              <1> 		; tst cdev / is the current device number non zero
  2600                              <1> 			 ; / (i.e., device =/ drum)
  2601 000051F5 7517                <1> 	jnz	short iget_3 ;  1f
  2602                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2603 000051F7 663B05[966E0000]    <1> 	cmp	ax, [mnti]			
  2604                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2605                              <1> 			    ; / file (root directory of mounted device)
  2606 000051FE 750E                <1> 	jne	short iget_3 ; 1f
  2607                              <1> 		; bne 1f
  2608                              <1>         ;mov    bl, [mntd]
  2609 00005200 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2610 00005202 8815[906E0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2611                              <1> 		; mov mntd,cdev / make mounted device the current device
  2612 00005208 66A1[9A6E0000]      <1> 	mov	ax, [rootdir]
  2613                              <1> 		; mov rootdir,r1
  2614                              <1> iget_3: ; 1:
  2615 0000520E 66A3[8C6E0000]      <1> 	mov	[ii], ax
  2616                              <1> 		; mov r1,ii
  2617 00005214 8815[8E6E0000]      <1> 	mov	[idev], dl ; cdev
  2618                              <1> 		; mov cdev,idev
  2619 0000521A 30DB                <1> 	xor	bl, bl
  2620                              <1>         ; 31/07/2013
  2621 0000521C 881D[286F0000]      <1> 	mov     [rw], bl ; 0 == read 
  2622                              <1> 	;;28/07/2013 rw -> u.rw       
  2623                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2624 00005222 E807000000          <1> 	call	icalc
  2625                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2626                              <1> iget_4: ; 2:
  2627 00005227 66A1[8C6E0000]      <1> 	mov	ax, [ii]
  2628                              <1> 		; mov ii,r1
  2629                              <1> iget_5:
  2630 0000522D C3                  <1> 	retn
  2631                              <1> 		; rts r0
  2632                              <1> 
  2633                              <1> icalc:
  2634                              <1> 	; 03/02/2022
  2635                              <1> 	; 02/07/2015
  2636                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2637                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2638                              <1> 	;
  2639                              <1> 	; calculate physical block number from i-number then
  2640                              <1> 	; read or write that block
  2641                              <1> 	;
  2642                              <1> 	; 'icalc' is called from 'iget'
  2643                              <1> 	;
  2644                              <1> 	; for original unix v1:
  2645                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2646                              <1>        	; / (i+31.) mod 16. bytes from its start
  2647                              <1> 	;
  2648                              <1> 	; for retro unix 8086 v1:
  2649                              <1> 	;  i-node is located in block (i+47)/16 and
  2650                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2651                              <1> 	;
  2652                              <1> 	; INPUTS ->
  2653                              <1> 	;    r1 - i-number of i-node
  2654                              <1> 	; 	 
  2655                              <1> 	; OUTPUTS ->
  2656                              <1> 	;    inode r/w
  2657                              <1> 	;
  2658                              <1> 	; ((AX = R1)) input
  2659                              <1> 	;
  2660                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2661                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2662                              <1> 	;
  2663 0000522E 0FB7D0              <1> 	movzx	edx, ax	
  2664 00005231 6683C22F            <1> 	add	dx, 47
  2665 00005235 89D0                <1> 	mov	eax, edx
  2666                              <1> 	;add	ax, 47	; add 47 to inode number
  2667                              <1> 		; add $31.,r1 / add 31. to i-number
  2668 00005237 50                  <1> 	push	eax
  2669                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2670                              <1> 	; 03/02/2022
  2671 00005238 C1E804              <1> 	shr	eax, 4
  2672                              <1> 	;shr 	ax, 4
  2673                              <1> 		; asr r1 / divide by 16.
  2674                              <1> 		; asr r1
  2675                              <1> 		; asr r1
  2676                              <1> 		; asr r1 / r1 contains block number of block
  2677                              <1> 		       ; / in which i-node exists
  2678 0000523B E83E0A0000          <1> 	call	dskrd
  2679                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2680                              <1> 	; 31/07/2013
  2681 00005240 803D[286F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2682                              <1> 	;; 28/07/2013 rw -> u.rw
  2683                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2684                              <1> 		; tst (r0)
  2685 00005247 7605                <1> 	jna	short icalc_1
  2686                              <1> 		; beq 1f / branch to wslot when argument
  2687                              <1> 		       ; / in icalc call = 1
  2688                              <1> 	; eAX = r1 = block number
  2689 00005249 E8A20A0000          <1> 	call	wslot
  2690                              <1> 		; jsr r0,wslot / set up data buffer for write
  2691                              <1> 			     ; / (will be same buffer as dskrd got)
  2692                              <1> 	; eBX = r5 points to first word in data area for this block
  2693                              <1> icalc_1: ; 1:
  2694 0000524E 5A                  <1> 	pop	edx 
  2695 0000524F 83E20F              <1> 	and 	edx, 0Fh ; (i+47) mod 16
  2696                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2697                              <1> 			      ; / gives (i+31.) mod 16
  2698 00005252 C1E205              <1> 	shl 	edx, 5
  2699                              <1> 	; eDX = 32 * ((i+47) mod 16)
  2700 00005255 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2701 00005257 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2702                              <1>           	; eSI (r5) points to first word in i-node i.	
  2703                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2704                              <1> 			     ; / 32.*(i+31.)mod16
  2705                              <1> 		; mov $5,lsh / for i-node i.
  2706                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2707 00005259 BF[A86B0000]        <1> 	mov	edi, inode
  2708                              <1> 		; mov $inode,r1 / inode is address of first word 
  2709                              <1> 			      ; / of current i-node
  2710                              <1> 	; 03/02/2022
  2711 0000525E 29C9                <1> 	sub	ecx, ecx
  2712 00005260 B108                <1> 	mov	cl, 8 
  2713                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2714                              <1> 		; mov $16.,r3
  2715                              <1>         ; 31/07/2013
  2716 00005262 382D[286F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2717                              <1>        ;;28/07/2013 rw -> u.rw                 
  2718                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2719                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2720 00005268 7609                <1> 	jna	short icalc_3
  2721                              <1> 		; beq 2f / r0 now contains proper return address 
  2722                              <1> 		       ; / for rts r0
  2723                              <1> icalc_2: ; 1:
  2724 0000526A 87F7                <1> 	xchg 	esi, edi
  2725                              <1> 	; overwrite old i-node (in buffer to be written)
  2726 0000526C F3A5                <1> 	rep 	movsd
  2727                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2728                              <1> 		; dec r3
  2729                              <1> 		; bgt 1b
  2730                              <1> 	;call	dskwr
  2731                              <1> 		; jsr r0,dskwr / write inode out on device
  2732                              <1> 	;retn
  2733                              <1> 		; rts r0
  2734                              <1> 	; 03/02/2022
  2735 0000526E E9990A0000          <1> 	jmp	dskwr
  2736                              <1> icalc_3: ; 2:
  2737                              <1> 	; copy new i-node into inode area of (core) memory
  2738 00005273 F3A5                <1> 	rep 	movsd
  2739                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2740                              <1> 		                ; / "inode" area of core
  2741                              <1> 		; dec r3
  2742                              <1> 		; bgt 2b
  2743 00005275 C3                  <1> 	retn
  2744                              <1> 		; rts r0
  2745                              <1> 
  2746                              <1> access:
  2747                              <1> 	; 03/02/2022
  2748                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2749                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2750                              <1> 	;
  2751                              <1> 	; check whether user is owner of file or user has read or write
  2752                              <1> 	; permission (based on i.flgs).
  2753                              <1> 	;
  2754                              <1> 	; INPUTS ->
  2755                              <1> 	;    r1 - i-number of file
  2756                              <1> 	;    u.uid
  2757                              <1> 	; arg0 -> (owner flag mask)	 		
  2758                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2759                              <1> 	; OUTPUTS ->
  2760                              <1> 	;    inode (or jump to error)
  2761                              <1> 	;
  2762                              <1> 	; ((AX = R1)) input/output
  2763                              <1> 	;
  2764                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2765                              <1> 	;
  2766                              <1> 
  2767                              <1> 	;push	dx  ; save flags (DL)
  2768                              <1> 	; 03/02/2022
  2769 00005276 52                  <1> 	push	edx ; save flags (DL)
  2770 00005277 E826FFFFFF          <1> 	call	iget
  2771                              <1> 		; jsr r0,iget / read in i-node for current directory
  2772                              <1> 			    ; / (i-number passed in r1)
  2773 0000527C 8A0D[A86B0000]      <1> 	mov	cl, [i.flgs]
  2774                              <1> 		; mov i.flgs,r2
  2775                              <1> 	; 03/02/2022
  2776 00005282 5A                  <1> 	pop	edx ; restore flags (DL)
  2777                              <1> 	;pop	dx  ; restore flags (DL)
  2778 00005283 8A35[F26E0000]      <1> 	mov	dh, [u.uid]
  2779 00005289 3A35[AB6B0000]      <1> 	cmp	dh, [i.uid]
  2780                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2781 0000528F 7503                <1> 	jne	short access_1
  2782                              <1> 		; bne 1f / no, then branch
  2783 00005291 C0E902              <1> 	shr	cl, 2
  2784                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2785                              <1> 		        ; / read/write bits
  2786                              <1> 		; asrb r2
  2787                              <1> access_1: ; 1:
  2788 00005294 20D1                <1> 	and	cl, dl
  2789                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2790                              <1> 			     ; / in access call
  2791 00005296 7513                <1> 	jnz	short access_2
  2792                              <1> 		; bne 1f
  2793 00005298 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2794                              <1> 		; tstb u.uid
  2795 0000529A 740F                <1> 	jz	short access_2 ; yes, super user
  2796                              <1> 	;jnz	error
  2797                              <1> 		; beq 1f
  2798                              <1> 		; jmp error
  2799 0000529C C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2799 000052A4 0000                <1>
  2800                              <1> 			; 'permission denied !' error
  2801 000052A6 E93BE8FFFF          <1> 	jmp	error
  2802                              <1> 
  2803                              <1> access_2: ; 1:
  2804                              <1> 	; DL = flags
  2805 000052AB C3                  <1> 	retn
  2806                              <1> 		; rts r0
  2807                              <1> 
  2808                              <1> setimod:
  2809                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2810                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2811                              <1> 	;
  2812                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2813                              <1> 	; the inode has been modified. Also puts the time of modification
  2814                              <1> 	; into the inode.
  2815                              <1> 	;
  2816                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2817                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2818                              <1> 	;
  2819                              <1> 	
  2820                              <1> 	; push 	edx
  2821 000052AC 50                  <1> 	push	eax
  2822                              <1> 
  2823 000052AD C605[9E6E0000]01    <1> 	mov 	byte [imod], 1
  2824                              <1> 		; movb $1,imod / set current i-node modified bytes
  2825                              <1> 	; Erdogan Tan 14-7-2012
  2826 000052B4 E870E3FFFF          <1> 	call 	epoch
  2827                              <1> 		 ; mov s.time,i.mtim 
  2828                              <1> 			    ; / put present time into file modified time
  2829                              <1> 		 ; mov s.time+2,i.mtim+2
  2830                              <1> 
  2831 000052B9 A3[C26B0000]        <1> 	mov 	[i.mtim], eax
  2832                              <1> 	
  2833                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2834                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2835 000052BE 833D[BE6B0000]00    <1> 	cmp	dword [i.ctim], 0
  2836 000052C5 7505                <1> 	jnz	short setimod_ok
  2837                              <1> 
  2838 000052C7 A3[BE6B0000]        <1> 	mov 	[i.ctim], eax
  2839                              <1> 
  2840                              <1> setimod_ok: ; 31/07/2013
  2841 000052CC 58                  <1> 	pop	eax
  2842                              <1> 	;pop	edx
  2843                              <1> 	
  2844 000052CD C3                  <1> 	retn
  2845                              <1> 		; rts r0
  2846                              <1> 
  2847                              <1> itrunc:
  2848                              <1> 	; 03/02/2022
  2849                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2850                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2851                              <1> 	;
  2852                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2853                              <1> 	;  to zero length.
  2854                              <1> 	;
  2855                              <1> 	; INPUTS ->
  2856                              <1> 	;    r1 - i-number of i-node
  2857                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2858                              <1> 	;    i.flgs - large file flag		
  2859                              <1> 	;    i.size - size of file	
  2860                              <1> 	; 	 
  2861                              <1> 	; OUTPUTS ->
  2862                              <1> 	;    i.flgs - large file flag is cleared
  2863                              <1> 	;    i.size - set to 0	
  2864                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2865                              <1> 	;    setimod - set to indicate i-node has been modified
  2866                              <1> 	;    r1 - i-number of i-node  					
  2867                              <1> 	;
  2868                              <1> 	; ((AX = R1)) input/output
  2869                              <1> 	;
  2870                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2871                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2872                              <1> 
  2873 000052CE E8CFFEFFFF          <1> 	call	iget
  2874                              <1> 		; jsr r0,iget
  2875 000052D3 BE[AE6B0000]        <1> 	mov	esi, i.dskp
  2876                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2877 000052D8 31C0                <1> 	xor	eax, eax
  2878                              <1> itrunc_1: ; 1:
  2879 000052DA 66AD                <1> 	lodsw
  2880                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2881                              <1> 	; 03/02/2022
  2882 000052DC 09C0                <1> 	or	eax, eax
  2883                              <1> 	;or 	ax, ax
  2884 000052DE 7433                <1> 	jz	short itrunc_5
  2885                              <1> 		; beq 5f
  2886 000052E0 56                  <1> 	push	esi
  2887                              <1> 		; mov r2,-(sp)
  2888                              <1> 	; 03/02/2022
  2889 000052E1 F605[A96B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2890                              <1> 	;test	word [i.flgs], 1000h
  2891                              <1> 		; bit $10000,i.flgs / test large file bit?
  2892 000052E8 7423                <1> 	jz	short itrunc_4
  2893                              <1> 		; beq 4f / if clear, branch
  2894 000052EA 50                  <1> 	push	eax
  2895                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2896 000052EB E88E090000          <1> 	call	dskrd
  2897                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2898                              <1> 			     ; / pointed to by r5
  2899                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2900                              <1> 	; 03/02/2022
  2901 000052F0 31C9                <1> 	xor	ecx, ecx
  2902 000052F2 FEC5                <1> 	inc	ch ; mov ch, 1
  2903                              <1> 	; ecx = 256
  2904                              <1> 	;mov	ecx, 256
  2905                              <1> 		; mov $256.,r3 / move word count into r3
  2906 000052F4 89DE                <1> 	mov	esi, ebx
  2907                              <1> itrunc_2: ; 2:
  2908 000052F6 66AD                <1> 	lodsw
  2909                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2910                              <1> 			     ; / physical block number
  2911                              <1> 	; 03/02/2022
  2912 000052F8 21C0                <1> 	and	eax, eax
  2913                              <1> 	;and	ax, ax
  2914 000052FA 7407                <1> 	jz	short itrunc_3
  2915                              <1> 		; beq 3f / branch if zero
  2916                              <1> 	; 03/02/2022
  2917 000052FC 51                  <1> 	push	ecx
  2918                              <1> 	;push	cx
  2919                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2920                              <1> 	;push	esi
  2921                              <1> 		; mov r5,-(sp)
  2922 000052FD E855FEFFFF          <1> 	call	free
  2923                              <1> 		; jsr r0,free / free block in free storage map
  2924                              <1> 	;pop	esi
  2925                              <1> 		; mov(sp)+,r5
  2926                              <1> 	;pop	cx
  2927 00005302 59                  <1> 	pop	ecx
  2928                              <1> 		; mov (sp)+,r3
  2929                              <1> itrunc_3: ; 3:
  2930 00005303 E2F1                <1> 	loop	itrunc_2
  2931                              <1> 		; dec r3 / decrement word count
  2932                              <1> 		; bgt 2b / branch if positive
  2933 00005305 58                  <1> 	pop	eax
  2934                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2935                              <1> 			     ; / indirect block
  2936                              <1> 	; 01/08/2013
  2937                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2938                              <1> 	; 03/02/2022
  2939 00005306 8025[A96B0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2940                              <1> itrunc_4: ; 4:
  2941 0000530D E845FEFFFF          <1> 	call	free
  2942                              <1> 		; jsr r0,free / free indirect block
  2943 00005312 5E                  <1> 	pop	esi
  2944                              <1> 		; mov (sp)+,r2
  2945                              <1> itrunc_5: ; 5:
  2946 00005313 81FE[BE6B0000]      <1> 	cmp	esi, i.dskp+16
  2947                              <1> 		; cmp r2,$i.dskp+16.
  2948 00005319 72BF                <1> 	jb	short itrunc_1	
  2949                              <1> 		; bne 1b / branch until all i.dskp entries check
  2950                              <1> 	; 03/02/2022
  2951                              <1> 	;and	byte [i.flgs+1], 0EFh
  2952                              <1> 	; 01/08/2013
  2953                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2954                              <1> 		; bic $10000,i.flgs / clear large file bit
  2955 0000531B BF[AE6B0000]        <1> 	mov	edi, i.dskp
  2956                              <1> 	;mov	cx, 8
  2957                              <1> 	;xor 	ax, ax
  2958                              <1> 	; 03/02/2022
  2959 00005320 29C9                <1> 	sub	ecx, ecx
  2960 00005322 B108                <1> 	mov	cl, 8
  2961 00005324 29C0                <1> 	sub	eax, eax
  2962 00005326 66A3[AC6B0000]      <1> 	mov	[i.size], ax ; 0
  2963                              <1> 		; clr i.size / zero file size
  2964 0000532C F366AB              <1> 	rep	stosw
  2965                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2966                              <1> 			   ; / zero block pointers
  2967 0000532F E878FFFFFF          <1> 	call	setimod
  2968                              <1> 		; jsr r0,setimod / set i-node modified flag
  2969 00005334 66A1[8C6E0000]      <1> 	mov	ax, [ii]
  2970                              <1> 		; mov ii,r1
  2971 0000533A C3                  <1> 	retn
  2972                              <1> 		; rts r0
  2973                              <1> 
  2974                              <1> imap:
  2975                              <1> 	; 12/02/2022
  2976                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2977                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2978                              <1> 	;
  2979                              <1> 	; 'imap' finds the byte in core (superblock) containing
  2980                              <1> 	; allocation bit for an i-node whose number in r1.
  2981                              <1> 	;
  2982                              <1> 	; INPUTS ->
  2983                              <1> 	;    r1 - contains an i-number
  2984                              <1> 	;    fsp - start of table containing open files
  2985                              <1> 	;
  2986                              <1> 	; OUTPUTS ->
  2987                              <1> 	;    r2 - byte address of byte with the allocation bit
  2988                              <1> 	;    mq - a mask to locate the bit position.	
  2989                              <1> 	;	  (a 1 is in calculated bit posisiton)
  2990                              <1> 	;
  2991                              <1> 	; ((AX = R1)) input/output
  2992                              <1> 	; ((DL/DX = MQ)) output
  2993                              <1> 	; ((BX = R2)) output
  2994                              <1> 	;
  2995                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  2996                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  2997                              <1> 	;
  2998                              <1> 		; / get the byte that has the allocation bit for 
  2999                              <1> 		; / the i-number contained in r1
  3000                              <1> 	;mov	dx, 1
  3001 0000533B B201                <1> 	mov	dl, 1
  3002                              <1> 		; mov $1,mq / put 1 in the mq
  3003 0000533D 0FB7D8              <1> 	movzx	ebx, ax
  3004                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3005                              <1>  		          ; / in the map we must find
  3006 00005340 6683EB29            <1> 	sub	bx, 41
  3007                              <1> 		; sub $41.,r2 / r2 has i-41
  3008 00005344 88D9                <1> 	mov	cl, bl
  3009                              <1> 		; mov r2,r3 / r3 has i-41
  3010 00005346 80E107              <1> 	and	cl, 7
  3011                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3012                              <1> 			   ; / the bit position
  3013 00005349 7402                <1> 	jz	short imap1
  3014                              <1> 	;shl	dx, cl
  3015 0000534B D2E2                <1> 	shl	dl, cl
  3016                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3017                              <1> imap1:			   ; / to the left to mask the correct bit
  3018                              <1> 	; 03/02/2022
  3019 0000534D C1EB03              <1> 	shr	ebx, 3
  3020                              <1> 	;shr	bx, 3
  3021                              <1> 		; asr r2
  3022                              <1> 		; asr r2
  3023                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3024                              <1> 		       ; / from the start of the map
  3025                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3026 00005350 BE[647B0000]        <1> 	mov	esi, systm
  3027                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3028                              <1> 				; / the super block for drum
  3029                              <1> 	;cmp	word [cdev], 0
  3030 00005355 803D[906E0000]00    <1> 	cmp	byte [cdev], 0
  3031                              <1> 		; tst cdev / is the device the disk
  3032 0000535C 7606                <1> 	jna	short imap2
  3033                              <1> 		; beq 1f / yes
  3034 0000535E 81C608020000        <1> 	add	esi, mount - systm
  3035                              <1> 		; add $mount-systm,r2 / for mounted device,
  3036                              <1> 			; / r2 points to 1st word of its super block
  3037                              <1> imap2: ; 1:
  3038 00005364 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3039                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3040 00005367 6683C304            <1> 	add	bx, 4
  3041 0000536B 01F3                <1> 	add	ebx, esi
  3042                              <1>         	; add (sp)+,r2 / ?
  3043                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3044                              <1> 		      ;; (2 + free map size + 2)
  3045                              <1> 		; add $2,r2 / ?
  3046                              <1>  	
  3047                              <1> 	; 12/02/2022
  3048 0000536D 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3049 00005373 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3050                              <1> 			  ; if inode num overs inode count
  3051                              <1> 
  3052                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3053                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3054                              <1> 
  3055                              <1> 	; 11/02/2022
  3056                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3057                              <1> 	;	(number of requested inode > inode count)
  3058                              <1> 
  3059 00005375 C3                  <1> 	retn
  3060                              <1> 		; rts r0
  2051                                  %include 'u6.s'        ; 31/05/2015
  2052                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  2053                              <1> ; Last Modification: 03/02/2022
  2054                              <1> ; ----------------------------------------------------------------------------
  2055                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2056                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2057                              <1> ;
  2058                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2059                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2060                              <1> ; <Bell Laboratories (17/3/1972)>
  2061                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2062                              <1> ;
  2063                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2064                              <1> ;
  2065                              <1> ; ****************************************************************************
  2066                              <1> ; 18/11/2015
  2067                              <1> 
  2068                              <1> readi:
  2069                              <1> 	; 03/02/2022
  2070                              <1> 	; 20/05/2015
  2071                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2072                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2073                              <1> 	;
  2074                              <1> 	; Reads from an inode whose number in R1
  2075                              <1> 	; 
  2076                              <1> 	; INPUTS ->
  2077                              <1> 	;    r1 - inode number
  2078                              <1> 	;    u.count - byte count user desires
  2079                              <1> 	;    u.base - points to user buffer
  2080                              <1> 	;    u.fofp - points to word with current file offset
  2081                              <1> 	; OUTPUTS ->
  2082                              <1> 	;    u.count - cleared
  2083                              <1> 	;    u.nread - accumulates total bytes passed back
  2084                              <1> 	;
  2085                              <1> 	; ((AX = R1)) input/output
  2086                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2087                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2088                              <1> 
  2089 00005376 31D2                <1> 	xor	edx, edx ; 0
  2090 00005378 8915[D46E0000]      <1> 	mov 	[u.nread], edx ; 0
  2091                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2092 0000537E 668915[0B6F0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2093 00005385 3915[D06E0000]      <1> 	cmp 	[u.count], edx ; 0
  2094                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2095 0000538B 7701                <1> 	ja 	short readi_1 ; 1f
  2096                              <1> 		 ; bgt 1f / yes, branch
  2097 0000538D C3                  <1> 	retn
  2098                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2099                              <1> readi_1: ; 1:
  2100                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2101 0000538E 6683F828            <1> 	cmp	ax, 40
  2102                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2103                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2104                              <1>         ;ja	dskr 
  2105                              <1> 		 ; ble 1f / yes, branch
  2106                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2107                              <1> 		 ;         / read file with i-node number (r1)
  2108                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2109                              <1> 	; 03/02/2022
  2110 00005392 7605                <1> 	jna	short readi_3
  2111 00005394 E9CF000000          <1> 	jmp	dskr
  2112                              <1> readi_3:
  2113                              <1> 	; (20/05/2015)
  2114 00005399 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2115                              <1> 	; 1:
  2116 0000539A 0FB6D8              <1> 	movzx	ebx, al
  2117                              <1> 	; 03/02/2022
  2118 0000539D C1E302              <1> 	shl	ebx, 2
  2119                              <1> 	;shl	bx, 2
  2120                              <1> 		 ; asl r1 / multiply inode number by 2
  2121 000053A0 81C3[A4530000]      <1> 	add	ebx, readi_2 - 4
  2122 000053A6 FF23                <1> 	jmp	dword [ebx]	
  2123                              <1> 		 ; jmp *1f-2(r1)
  2124                              <1> readi_2: ; 1:
  2125 000053A8 [F4530000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2126                              <1> 		 ;rtty / tty; r1=2
  2127                              <1> 		 ;rppt / ppt; r1=4
  2128 000053AC [44540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2129                              <1> 		 ;rmem / mem; r1=6
  2130                              <1> 		 ;rrf0 / rf0
  2131                              <1> 		 ;rrk0 / rk0
  2132                              <1> 		 ;rtap / tap0
  2133                              <1> 		 ;rtap / tap1
  2134                              <1> 		 ;rtap / tap2
  2135                              <1> 		 ;rtap / tap3
  2136                              <1> 		 ;rtap / tap4
  2137                              <1> 		 ;rtap / tap5
  2138                              <1> 		 ;rtap / tap6
  2139                              <1> 		 ;rtap / tap7
  2140 000053B0 [2F5B0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2141 000053B4 [2F5B0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2142 000053B8 [2F5B0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2143 000053BC [2F5B0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2144 000053C0 [2F5B0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2145 000053C4 [2F5B0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2146 000053C8 [59540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2147 000053CC [40540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2148                              <1> 		 ;rcvt / tty0
  2149 000053D0 [40540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2150                              <1> 		 ;rcvt / tty1
  2151 000053D4 [40540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2152                              <1> 		 ;rcvt / tty2
  2153 000053D8 [40540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2154                              <1> 		 ;rcvt / tty3
  2155 000053DC [40540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2156                              <1> 		 ;rcvt / tty4
  2157 000053E0 [40540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2158                              <1> 		 ;rcvt / tty5
  2159 000053E4 [40540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2160                              <1> 		 ;rcvt / tty6
  2161 000053E8 [40540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2162                              <1> 		 ;rcvt / tty7
  2163 000053EC [40540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2164                              <1> 		 ;rcrd / crd
  2165 000053F0 [40540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2166                              <1> 
  2167                              <1> rtty: ; / read from console tty
  2168                              <1> 	; 03/02/2022
  2169                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2170                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2171                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2172                              <1> 	;	     must be written immediate on video page (screen)
  2173                              <1> 	;	     when it is required.	
  2174                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2175                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2176                              <1> 	;
  2177                              <1> 	; Console tty buffer is PC keyboard buffer
  2178                              <1> 	; and keyboard-keystroke handling is different than original
  2179                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2180                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2181                              <1> 	;
  2182                              <1> 	; 06/12/2013
  2183 000053F4 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2184 000053FB 8A83[076C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2185                              <1> rttys:
  2186                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2187                              <1> 	               ; / of the control and status block
  2188                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2189                              <1> 		       ; / tty buffer
  2190                              <1> 	; 28/07/2013
  2191 00005401 A2[FA6E0000]        <1> 	mov 	[u.ttyn], al
  2192                              <1> 	; 13/01/2014
  2193 00005406 FEC0                <1> 	inc	al
  2194 00005408 A2[DC6E0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2195                              <1> rtty_nc: ; 01/02/2014
  2196                              <1> 	; 29/09/2013
  2197                              <1> 	;mov	ecx, 10
  2198                              <1> 	; 03/02/2022
  2199 0000540D 29C9                <1> 	sub	ecx, ecx
  2200 0000540F B10A                <1> 	mov	cl, 10
  2201                              <1> rtty_1: 	; 01/02/2014
  2202                              <1> 	;push 	cx ; 29/09/2013
  2203                              <1> 	; 03/02/2022
  2204 00005411 51                  <1> 	push	ecx
  2205                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2206 00005412 B001                <1> 	mov 	al, 1
  2207 00005414 E8660B0000          <1> 	call 	getc
  2208                              <1> 	; 03/02/2022
  2209 00005419 59                  <1> 	pop	ecx
  2210                              <1> 	;pop 	cx ; 29/09/2013	
  2211 0000541A 7516                <1> 	jnz	short rtty_2
  2212                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2213                              <1> 	               ; / of chars. Is this number non-zero?
  2214 0000541C E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2215                              <1> 	; 05/10/2013
  2216 0000541E 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn]
  2217                              <1> 	; 29/09/2013
  2218 00005424 E89AFBFFFF          <1> 	call	sleep
  2219                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2220                              <1>                 ;           / (120 chars.)
  2221                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2222 00005429 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2223                              <1> 
  2224                              <1> rtty_idle:
  2225                              <1> 	; 29/07/2013
  2226 0000542B E806FBFFFF          <1> 	call 	idle
  2227 00005430 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2228                              <1> 	;1:
  2229                              <1> 		; tst 2(r5) / is the number of characters zero
  2230                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2231                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2232                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2233                              <1> 		          ; / contains the next char.
  2234                              <1> 		; dec 2(r5) / decrement the character count
  2235                              <1> rtty_2:
  2236 00005432 30C0                <1> 	xor 	al, al
  2237 00005434 E8460B0000          <1> 	call 	getc
  2238 00005439 E892000000          <1> 	call	passc
  2239                              <1> 		; jsr r0,passc / move the character to core (user)
  2240                              <1> 	;; 17/10/2015 - 16/07/2015
  2241                              <1> 	; 19/06/2014
  2242                              <1> 	;;jnz	short rtty_nc
  2243 0000543E 58                  <1> 	pop	eax  ; (20/05/2015)
  2244 0000543F C3                  <1> 	retn 
  2245                              <1> ;ret1:
  2246                              <1> 		; jmp ret / return to caller via 'ret'
  2247                              <1> 
  2248                              <1> rcvt:   ; < receive/read character from tty >
  2249                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2250                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2251                              <1> 	;
  2252                              <1> 	; Retro UNIX 8086 v1 modification !
  2253                              <1> 	; 
  2254                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2255                              <1> 	;		(exactly different than this one)
  2256                              <1> 	;	was in 'u9.s' file.
  2257                              <1> 	;
  2258 00005440 2C0A                <1> 	sub 	al, 10
  2259                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2260                              <1> 	; 16/07/2013
  2261                              <1> 	; 21/05/2013
  2262 00005442 EBBD                <1>         jmp     short rttys
  2263                              <1>       
  2264                              <1> ;rppt: / read paper tape
  2265                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2266                              <1> ;			 / places
  2267                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2268                              <1> ;		       / also enables read bit in prs
  2269                              <1> ;	jsr	r0,passc / place character in users buffer area
  2270                              <1> ;	br	rppt
  2271                              <1> 
  2272                              <1> rmem: ; / transfer characters from memory to a user area of core
  2273                              <1> 	; 17/10/2015
  2274                              <1> 	; 11/06/2015
  2275                              <1> 	; 24/05/2015
  2276                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2277                              <1> 	;
  2278 00005444 8B35[BC6E0000]      <1> 	mov     esi, [u.fofp]
  2279                              <1> rmem_1:
  2280 0000544A 8B1E                <1>         mov     ebx, [esi]        
  2281                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2282                              <1> 		               ; / to be transferred to user
  2283 0000544C FF06                <1>         inc     dword [esi] ; 17/10/2015
  2284                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2285                              <1> 			    ; / char in memory file
  2286 0000544E 8A03                <1> 	mov	al, [ebx]
  2287                              <1> 		; movb (r1),r1 / get character from memory file, 
  2288                              <1> 		             ; / put it in r1
  2289 00005450 E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2290                              <1> 			     ;  / the next byte of the users core area
  2291                              <1> 		; br rmem / continue
  2292 00005455 75F3                <1> 	jnz	short rmem_1
  2293                              <1> ret_:
  2294 00005457 58                  <1> 	pop	eax ; 09/06/2015
  2295 00005458 C3                  <1> 	retn
  2296                              <1> 
  2297                              <1> rlpr:
  2298                              <1> ;1:
  2299                              <1> ;rcrd:
  2300 00005459 C705[FB6E0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2300 00005461 0000                <1>
  2301 00005463 E97EE6FFFF          <1> 	jmp	error
  2302                              <1> 		;jmp	error / see 'error' routine
  2303                              <1> 
  2304                              <1> dskr:
  2305                              <1> 	; 12/10/2015
  2306                              <1> 	; 21/08/2015
  2307                              <1> 	; 25/07/2015
  2308                              <1> 	; 10/07/2015
  2309                              <1> 	; 16/06/2015
  2310                              <1> 	; 31/05/2015
  2311                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2312                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2313                              <1> dskr_0:
  2314 00005468 50                  <1> 	push	eax
  2315                              <1> 		; mov (sp),r1 / i-number in r1
  2316                              <1> 	; AX = i-number
  2317 00005469 E834FDFFFF          <1> 	call	iget
  2318                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2319 0000546E 0FB715[AC6B0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2320                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2321 00005475 8B1D[BC6E0000]      <1> 	mov	ebx, [u.fofp]
  2322 0000547B 2B13                <1> 	sub	edx, [ebx]
  2323                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2324                              <1>         ; 12/10/2015
  2325                              <1> 	; jna     short ret_ 
  2326                              <1> 		; blos ret
  2327 0000547D 7709                <1> 	ja	short dskr_1
  2328                              <1> 	;
  2329                              <1> dskr_retn: ; 12/10/2015
  2330 0000547F 58                  <1> 	pop	eax
  2331 00005480 C605[0D6F0000]00    <1> 	mov	byte [u.kcall], 0
  2332 00005487 C3                  <1> 	retn	
  2333                              <1> dskr_1: 
  2334 00005488 3B15[D06E0000]      <1> 	cmp     edx, [u.count] 
  2335                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2336                              <1> 			       ; / to carry out read
  2337 0000548E 7306                <1> 	jnb	short dskr_2
  2338                              <1> 		; bhis 1f
  2339 00005490 8915[D06E0000]      <1> 	mov	[u.count], edx
  2340                              <1> 		; mov r2,u.count / no, just read to end of file
  2341                              <1> dskr_2: ; 1:
  2342                              <1> 	; AX = i-number
  2343 00005496 E8A0FBFFFF          <1> 	call	mget
  2344                              <1> 		; jsr r0,mget / returns physical block number of block 
  2345                              <1> 			    ; / in file where offset points
  2346                              <1> 	; eAX = physical block number
  2347 0000549B E8DE070000          <1> 	call	dskrd
  2348                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2349                              <1> 			     ; / 1st word of data in buffer
  2350                              <1> 	; 09/06/2015
  2351 000054A0 803D[0D6F0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2352 000054A7 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2353 000054A9 66833D[0B6F0000]00  <1> 	cmp	word [u.pcount], 0
  2354 000054B1 7705                <1> 	ja	short dskr_4
  2355                              <1> dskr_3:
  2356                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2357 000054B3 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2358                              <1> dskr_4:
  2359                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2360 000054B8 E8BC020000          <1> 	call	sioreg
  2361                              <1> 		; jsr r0,sioreg
  2362 000054BD 87F7                <1> 	xchg	esi, edi
  2363                              <1> 	; eDI = file (user data) offset
  2364                              <1> 	; eSI = sector (I/O) buffer offset
  2365                              <1> 	; eCX = byte count
  2366 000054BF F3A4                <1> 	rep	movsb
  2367                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2368                              <1> 		                 ; / starting at u.base
  2369                              <1> 		; dec r3
  2370                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2371                              <1> 	; 25/07/2015
  2372                              <1> 	; eax = remain bytes in buffer
  2373                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2374 000054C1 09C0                <1> 	or	eax, eax
  2375 000054C3 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2376                              <1> 	; 03/08/2013
  2377                              <1> 	;pop	eax
  2378 000054C5 390D[D06E0000]      <1> 	cmp	[u.count], ecx ; 0
  2379                              <1> 		; tst u.count / all bytes read off disk
  2380                              <1> 		; bne dskr
  2381                              <1> 		; br ret
  2382                              <1>         ;ja      short dskr_0
  2383                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2384                              <1> 	;retn
  2385                              <1> 	; 12/10/2015
  2386 000054CB 76B2                <1> 	jna	short dskr_retn
  2387 000054CD 58                  <1> 	pop	eax  ; (i-node number)
  2388 000054CE EB98                <1> 	jmp	short dskr_0
  2389                              <1> 	
  2390                              <1> passc:
  2391                              <1> 	; 18/10/2015
  2392                              <1> 	; 10/07/2015
  2393                              <1> 	; 01/07/2015
  2394                              <1> 	; 08/06/2015
  2395                              <1> 	; 04/06/2015
  2396                              <1> 	; 20/05/2015
  2397                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2398                              <1> 	;
  2399                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2400                              <1> 	;		      to physical address
  2401 000054D0 66833D[0B6F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2402                              <1> 			     ; 1-4095 --> use previous physical base address
  2403                              <1> 			     ; in [u.pbase]
  2404 000054D8 7705                <1> 	ja	short passc_3
  2405                              <1> 	; 08/06/2015 - 10/07/2015
  2406 000054DA E82C000000          <1> 	call	trans_addr_w
  2407                              <1> passc_3:
  2408                              <1> 	; 19/05/2015
  2409 000054DF 66FF0D[0B6F0000]    <1> 	dec	word [u.pcount]
  2410                              <1> 	;
  2411 000054E6 8B1D[076F0000]      <1> 	mov	ebx, [u.pbase]
  2412 000054EC 8803                <1> 	mov	[ebx], al
  2413                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2414                              <1> 		               ; / users buffer
  2415 000054EE FF05[CC6E0000]      <1> 	inc	dword [u.base]
  2416                              <1> 		; inc u.base / increment the pointer to point to 
  2417                              <1> 			  ; / the next byte in users buffer
  2418 000054F4 FF05[076F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2419 000054FA FF05[D46E0000]      <1> 	inc	dword [u.nread]
  2420                              <1> 		; inc u.nread / increment the number of bytes read
  2421 00005500 FF0D[D06E0000]      <1> 	dec	dword [u.count]
  2422                              <1> 		; dec u.count / decrement the number of bytes to be read
  2423                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2424 00005506 C3                  <1> 	retn
  2425                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2426                              <1> 		             ; / 'readi' by:
  2427                              <1> 		;/ (1) pop the return address off the stack into r0
  2428                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2429                              <1> 	;1:
  2430                              <1> 		; clr	*$ps / clear processor status
  2431                              <1> 		; rts r0 / return to address currently on top of stack
  2432                              <1> 
  2433                              <1> trans_addr_r:
  2434                              <1> 	; Translate virtual address to physical address 
  2435                              <1> 	; for reading from user's memory space
  2436                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2437                              <1> 	; 18/10/2015
  2438                              <1> 	; 10/07/2015
  2439                              <1> 	; 09/06/2015
  2440                              <1> 	; 08/06/2015 
  2441                              <1> 	; 04/06/2015
  2442                              <1> 	;
  2443                              <1> 	; 18/10/2015
  2444 00005507 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2445 00005509 EB04                <1> 	jmp 	short trans_addr_rw
  2446                              <1> 
  2447                              <1> 	;push	eax
  2448                              <1> 	;push	ebx
  2449                              <1> 	;mov	ebx, [u.base]
  2450                              <1> 	;call	get_physical_addr ; get physical address
  2451                              <1> 	;;jnc	short cpass_0
  2452                              <1> 	;jnc	short passc_1
  2453                              <1> 	;mov	[u.error], eax
  2454                              <1> 	;;pop	ebx
  2455                              <1> 	;;pop	eax
  2456                              <1> 	;jmp	error
  2457                              <1> ;cpass_0:
  2458                              <1> 	; 18/10/2015
  2459                              <1> 	; 20/05/2015
  2460                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2461                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2462                              <1> 	;pop	ebx
  2463                              <1> 	;pop	eax
  2464                              <1> 	;retn	; 08/06/2015
  2465                              <1> 
  2466                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2467                              <1> trans_addr_w:
  2468                              <1> 	; Translate virtual address to physical address 
  2469                              <1> 	; for writing to user's memory space
  2470                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2471                              <1> 	; 18/10/2015
  2472                              <1> 	; 29/07/2015
  2473                              <1> 	; 10/07/2015
  2474                              <1> 	; 09/06/2015
  2475                              <1> 	; 08/06/2015
  2476                              <1> 	; 04/06/2015 (passc)
  2477                              <1> 	;
  2478                              <1> 	; 18/10/2015
  2479 0000550B 29D2                <1> 	sub	edx, edx
  2480 0000550D FEC2                <1> 	inc	dl ; 1 (write access sign)
  2481                              <1> trans_addr_rw:
  2482 0000550F 50                  <1> 	push	eax
  2483 00005510 53                  <1> 	push	ebx
  2484                              <1> 	; 18/10/2015
  2485 00005511 52                  <1> 	push 	edx ; r/w sign (in DL)
  2486                              <1> 	;
  2487 00005512 8B1D[CC6E0000]      <1> 	mov	ebx, [u.base]
  2488 00005518 E8A3DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2489 0000551D 730A                <1> 	jnc	short passc_0
  2490 0000551F A3[FB6E0000]        <1> 	mov	[u.error], eax
  2491                              <1> 	;pop	edx
  2492                              <1> 	;pop 	ebx
  2493                              <1> 	;pop	eax
  2494 00005524 E9BDE5FFFF          <1> 	jmp	error
  2495                              <1> passc_0:
  2496 00005529 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2497 0000552C 5A                  <1> 	pop	edx ; 18/10/2015
  2498 0000552D 7517                <1> 	jnz	short passc_1
  2499                              <1> 	; 18/10/2015
  2500 0000552F 20D2                <1> 	and 	dl, dl
  2501 00005531 7413                <1> 	jz	short passc_1
  2502                              <1> 	; 20/05/2015
  2503                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2504                              <1> 	; EBX = linear address
  2505 00005533 51                  <1> 	push 	ecx
  2506 00005534 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2507 00005535 E8F5DBFFFF          <1> 	call 	copy_page
  2508 0000553A 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2509 0000553B 59                  <1> 	pop	ecx
  2510 0000553C 7217                <1> 	jc	short passc_2
  2511                              <1> 	; 03/02/2022
  2512                              <1> 	;push	eax ; physical address of the new/allocated page
  2513                              <1> 	;call	add_to_swap_queue
  2514                              <1> 	;pop	eax
  2515                              <1> 	; 18/10/2015
  2516 0000553E 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2517                              <1> 	;mov 	ecx, PAGE_SIZE
  2518                              <1> 	;sub	ecx, ebx 
  2519 00005544 01D8                <1> 	add	eax, ebx  
  2520                              <1> passc_1: 
  2521                              <1> 	; 18/10/2015
  2522                              <1> 	; 20/05/2015
  2523 00005546 A3[076F0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2524 0000554B 66890D[0B6F0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2525 00005552 5B                  <1> 	pop	ebx
  2526 00005553 58                  <1> 	pop	eax
  2527 00005554 C3                  <1> 	retn	; 08/06/2015
  2528                              <1> passc_2:
  2529 00005555 C705[FB6E0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2529 0000555D 0000                <1>
  2530                              <1> 	;pop 	ebx
  2531                              <1> 	;pop	eax
  2532 0000555F E982E5FFFF          <1> 	jmp	error
  2533                              <1> 
  2534                              <1> writei:
  2535                              <1> 	; 03/02/2022
  2536                              <1> 	; 20/05/2015
  2537                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2538                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2539                              <1> 	;
  2540                              <1> 	; Write data to file with inode number in R1
  2541                              <1> 	; 
  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> 	; ((AX = R1))
  2551                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2552                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2553                              <1> 
  2554 00005564 31C9                <1> 	xor	ecx, ecx
  2555 00005566 890D[D46E0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2556                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2557                              <1> 		            ; / read or write calls
  2558 0000556C 66890D[0B6F0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2559 00005573 390D[D06E0000]      <1> 	cmp 	[u.count], ecx
  2560                              <1> 	;	; tst u.count / test the byte count specified by the user
  2561 00005579 7701                <1> 	ja 	short writei_1 ; 1f
  2562                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2563 0000557B C3                  <1> 	retn
  2564                              <1> 	;	; rts r0 / no, return - no writing to do
  2565                              <1> writei_1: ;1:
  2566                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2567 0000557C 6683F828            <1> 	cmp 	ax, 40
  2568                              <1> 		; cmp r1,$40.
  2569                              <1> 		; / does the i-node number indicate a special file?
  2570                              <1> 	;ja	dskw 
  2571                              <1> 		; bgt dskw / no, branch to standard file output
  2572                              <1> 	; 03/02/2022
  2573 00005580 7605                <1> 	jna	short writei_3
  2574 00005582 E9ED000000          <1> 	jmp	dskw
  2575                              <1> writei_3:
  2576                              <1> 	; (20/05/2015)
  2577 00005587 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2578 00005588 0FB6D8              <1> 	movzx	ebx, al
  2579                              <1> 	; 03/02/2022
  2580 0000558B C1E302              <1> 	shl	ebx, 2
  2581                              <1> 	;shl	bx, 2
  2582                              <1> 		; asl r1 / yes, calculate the index into the special file
  2583 0000558E 81C3[92550000]      <1> 	add	ebx, writei_2 - 4
  2584 00005594 FF23                <1> 	jmp	dword [ebx]	
  2585                              <1> 		; jmp *1f-2(r1)
  2586                              <1> 		; / jump table and jump to the appropriate routine
  2587                              <1> writei_2: ;1:
  2588 00005596 [E2550000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2589                              <1> 		 ;wtty / tty; r1=2
  2590                              <1> 		 ;wppt / ppt; r1=4
  2591 0000559A [44560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2592                              <1> 		 ;wmem / mem; r1=6
  2593                              <1> 		 ;wrf0 / rf0
  2594                              <1> 		 ;wrk0 / rk0
  2595                              <1> 		 ;wtap / tap0
  2596                              <1> 		 ;wtap / tap1
  2597                              <1> 		 ;wtap / tap2
  2598                              <1> 		 ;wtap / tap3
  2599                              <1> 		 ;wtap / tap4
  2600                              <1> 		 ;wtap / tap5
  2601                              <1> 		 ;wtap / tap6
  2602                              <1> 		 ;wtap / tap7
  2603 0000559E [B85B0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2604 000055A2 [B85B0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2605 000055A6 [B85B0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2606 000055AA [B85B0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2607 000055AE [B85B0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2608 000055B2 [B85B0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2609 000055B6 [35560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2610 000055BA [2F560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2611                              <1> 		 ;xmtt / tty0
  2612 000055BE [2F560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2613                              <1> 		 ;xmtt / tty1
  2614 000055C2 [2F560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2615                              <1> 		 ;xmtt / tty2
  2616 000055C6 [2F560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2617                              <1> 		 ;xmtt / tty3
  2618 000055CA [2F560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2619                              <1> 		 ;xmtt / tty4
  2620 000055CE [2F560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2621                              <1> 		 ;xmtt / tty5
  2622 000055D2 [2F560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2623                              <1> 		 ;xmtt / tty6
  2624 000055D6 [2F560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2625                              <1> 		 ;xmtt / tty7
  2626 000055DA [2F560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2627                              <1> 		; / wlpr / lpr
  2628 000055DE [2F560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2629                              <1> 
  2630                              <1> wtty: ; write to console tty (write to screen)
  2631                              <1> 	; 03/02/2022
  2632                              <1> 	; 18/11/2015
  2633                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2634                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2635                              <1> 	;
  2636                              <1> 	; Console tty output is on current video page
  2637                              <1> 	; Console tty character output procedure is changed here
  2638                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2639                              <1> 	;
  2640 000055E2 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2641 000055E9 8AA3[076C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2642 000055EF 88E0                <1> 	mov	al, ah ; 07/07/2014
  2643                              <1> wttys:	
  2644                              <1> 	; 10/10/2013
  2645 000055F1 8825[FA6E0000]      <1> 	mov 	[u.ttyn], ah
  2646                              <1> 	; 13/01/2014
  2647 000055F7 FEC0                <1> 	inc	al
  2648 000055F9 A2[DD6E0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2649                              <1> wtty_nc: ; 15/05/2013
  2650                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2651 000055FE E816010000          <1> 	call	cpass
  2652                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2653                              <1> 		             ; / none go to return address in syswrite
  2654                              <1> 		; tst r1 / is character = null
  2655                              <1> 		; beq wtty / yes, get next character
  2656                              <1> 	; 10/10/2013
  2657 00005603 7428                <1> 	jz	short wret
  2658                              <1> 	;1 :
  2659                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2660                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2661                              <1> 		;	          / than 20
  2662                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2663                              <1> 	; 27/06/2014
  2664                              <1> wtty_1:
  2665                              <1> 	; AH = tty number
  2666                              <1> 	; AL = ASCII code of the character
  2667                              <1> 	; 15/04/2014
  2668                              <1> 	;push	ax
  2669                              <1> 	; 03/02/2022
  2670 00005605 50                  <1> 	push	eax
  2671 00005606 E8E2090000          <1> 	call	putc ; 14/05/2013
  2672 0000560B 731D                <1> 	jnc	short wtty_2
  2673                              <1> 	; 18/11/2015
  2674 0000560D E824F9FFFF          <1> 	call	idle
  2675                              <1> 	;mov	ax, [esp]
  2676                              <1> 	; 03/02/2022
  2677 00005612 8B0424              <1> 	mov	eax, [esp]
  2678 00005615 E8D3090000          <1> 	call	putc
  2679 0000561A 730E                <1> 	jnc	short wtty_2 
  2680                              <1> 	; 02/06/2014
  2681 0000561C 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn]
  2682 00005622 E89CF9FFFF          <1> 	call	sleep
  2683                              <1> 	; 03/02/2022
  2684 00005627 58                  <1> 	pop	eax
  2685                              <1> 	;pop	ax
  2686 00005628 EBDB                <1> 	jmp 	short wtty_1
  2687                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2688                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2689                              <1> 			      ; / console tty and
  2690                              <1> 		; br 	2f / place character in list; if none available
  2691                              <1> 		   	  ; / branch to put process to sleep
  2692                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2693                              <1> wtty_2:
  2694                              <1> 	; 15/04/2014
  2695                              <1> 	;pop	ax
  2696                              <1> 	; 03/02/2022
  2697 0000562A 58                  <1> 	pop	eax
  2698 0000562B EBD1                <1> 	jmp	short wtty_nc
  2699                              <1> 		; br wtty
  2700                              <1> wret:	; 10/10/2013 (20/05/2015)
  2701 0000562D 58                  <1> 	pop	eax
  2702 0000562E C3                  <1> 	retn
  2703                              <1> 	;2:
  2704                              <1> 		;mov	r1,-(sp) / place character on stack
  2705                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2706                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2707                              <1> 		;br	1b / try again to place character in clist and output
  2708                              <1> 
  2709                              <1> xmtt:   ; < send/write character to tty >
  2710                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2711                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2712                              <1> 	;
  2713                              <1> 	; Retro UNIX 8086 v1 modification !
  2714                              <1> 	; 
  2715                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2716                              <1> 	;		(exactly different than this one)
  2717                              <1> 	;	was in 'u9.s' file.
  2718                              <1> 	;
  2719 0000562F 2C0A                <1> 	sub 	al, 10
  2720                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2721                              <1> 	; 10/10/2013
  2722 00005631 88C4                <1> 	mov	ah, al
  2723                              <1> 	; 28/07/2013
  2724 00005633 EBBC                <1> 	jmp	short wttys
  2725                              <1> 
  2726                              <1> ;wppt:
  2727                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2728                              <1> ;		         / if none return to writei's calling routine
  2729                              <1> ;	jsr	r0,pptoc / output character on ppt
  2730                              <1> ;	br	wppt
  2731                              <1> wlpr:
  2732 00005635 C705[FB6E0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2732 0000563D 0000                <1>
  2733 0000563F E9A2E4FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2734                              <1> 		;/	jsr	r0,cpass
  2735                              <1> 		;/	cmp	r0,$'a
  2736                              <1> 		;/	blo	1f
  2737                              <1> 		;/	cmp	r1,$'z
  2738                              <1> 		;/	bhi	1f
  2739                              <1> 		;/	sub	$40,r1
  2740                              <1> 		;/1:
  2741                              <1> 		;/	jsr	r0,lptoc
  2742                              <1> 		;/	br	wlpr
  2743                              <1> 		; br rmem / continue
  2744                              <1> 
  2745                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2746                              <1> 	; 17/10/2015
  2747                              <1> 	; 11/06/2015
  2748                              <1> 	; 24/05/2015
  2749                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2750                              <1> 	;
  2751 00005644 813D[29070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2751 0000564A [594F0000]          <1>
  2752 0000564E 7415                <1>         je      short wmem_acc_err
  2753                              <1> 	;
  2754 00005650 8B35[BC6E0000]      <1>         mov     esi, [u.fofp] 
  2755                              <1> wmem_1:
  2756 00005656 E8BE000000          <1> 	call	cpass
  2757                              <1> 		; jsr r0,cpass / get next character from users area of
  2758                              <1> 			     ; / core and put it in r1
  2759                              <1>         	; mov r1,-(sp) / put character on the stack
  2760                              <1> 	; 20/09/2013
  2761 0000565B 74D0                <1> 	jz	short wret ; wmem_2  
  2762 0000565D 8B1E                <1>         mov     ebx, [esi]
  2763                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2764 0000565F FF06                <1>         inc     dword [esi] ; 17/10/2015
  2765                              <1> 		; inc *u.fofp / increment file offset to point to next
  2766                              <1> 			    ; / available location in file
  2767 00005661 8803                <1> 	mov	[ebx], al	
  2768                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2769                              <1> 			        ; / assigned to it
  2770 00005663 EBF1                <1> 	jmp	short wmem_1
  2771                              <1> 		; br wmem / continue
  2772                              <1> 	;1:
  2773                              <1> 	;jmp	error / ?
  2774                              <1> ;wmem_2:	
  2775                              <1> ;	; 20/09/2013
  2776                              <1> ;	pop	ax
  2777                              <1> ;	retn
  2778                              <1> 
  2779                              <1> wmem_acc_err:
  2780 00005665 C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2780 0000566D 0000                <1>
  2781 0000566F E972E4FFFF          <1> 	jmp	error
  2782                              <1> 
  2783                              <1> dskw: ; / write routine for non-special files
  2784                              <1> 	;
  2785                              <1> 	; 03/02/2022
  2786                              <1> 	; 25/07/2015
  2787                              <1> 	; 16/06/2015
  2788                              <1> 	; 09/06/2015
  2789                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2790                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2791                              <1> 	;
  2792                              <1> 	; 01/08/2013 (mkdir_w check)
  2793                              <1> 
  2794                              <1> 	;push	ax ; 26/04/2013
  2795                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2796                              <1> 	; 03/02/2022
  2797 00005674 50                  <1> 	push	eax
  2798                              <1> 	; AX = inode number
  2799 00005675 E828FBFFFF          <1> 	call	iget
  2800                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2801                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2802 0000567A 8B1D[BC6E0000]      <1>         mov     ebx, [u.fofp] 
  2803 00005680 8B13                <1> 	mov 	edx, [ebx]
  2804                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2805                              <1> 			       ; / in the fsp entry for this file] in r2
  2806 00005682 0315[D06E0000]      <1> 	add 	edx, [u.count]	
  2807                              <1> 		; add u.count,r2 / no. of bytes to be written
  2808                              <1> 			       ; / + file offset is put in r2
  2809                              <1> 	; 16/06/2015        
  2810 00005688 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2811 0000568E 760F                <1> 	jna	short dskw_0
  2812 00005690 C705[FB6E0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2812 00005698 0000                <1>
  2813 0000569A E947E4FFFF          <1> 	jmp	error
  2814                              <1> dskw_0:	
  2815 0000569F 663B15[AC6B0000]    <1> 	cmp     dx, [i.size]
  2816                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2817                              <1> 		              ; / the file?
  2818 000056A6 760C                <1> 	jna	short dskw_1
  2819                              <1> 		; blos 1f / no, branch
  2820 000056A8 668915[AC6B0000]    <1>         mov     [i.size], dx
  2821                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2822                              <1> 			      ; / file offset + no. of data bytes
  2823 000056AF E8F8FBFFFF          <1> 	call	setimod
  2824                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2825                              <1> 		          ; / modified), stuff time of modification into
  2826                              <1> 	          	  ; / core image of i-node
  2827                              <1> dskw_1: ; 1:	
  2828 000056B4 E882F9FFFF          <1> 	call	mget
  2829                              <1> 	; eAX = Block number
  2830                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2831                              <1> 			    ; /	the next data byte
  2832                              <1> 	; eax = block number
  2833 000056B9 8B1D[BC6E0000]      <1> 	mov     ebx, [u.fofp]
  2834 000056BF 8B13                <1> 	mov	edx, [ebx]
  2835 000056C1 81E2FF010000        <1> 	and	edx, 1FFh  
  2836                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2837 000056C7 750C                <1> 	jnz	short dskw_2
  2838                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2839                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2840 000056C9 813D[D06E0000]0002- <1> 	cmp	dword [u.count], 512
  2840 000056D1 0000                <1>
  2841                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2842                              <1> 				  ; / an entire block? (i.e., no. of
  2843 000056D3 7305                <1> 	jnb	short dskw_3
  2844                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2845                              <1> 			; / Yes, branch. Don't have to read block
  2846                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2847                              <1>    		; / overwritten).
  2848 000056D5 E8A4050000          <1> 	call	dskrd
  2849                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2850                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2851                              <1> dskw_3: ; 3:
  2852                              <1> 	; eAX (r1) = block/sector number
  2853 000056DA E811060000          <1> 	call	wslot
  2854                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2855                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2856 000056DF 803D[0D6F0000]00    <1> 	cmp	byte [u.kcall], 0
  2857 000056E6 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2858                              <1> 	;
  2859 000056E8 66833D[0B6F0000]00  <1> 	cmp	word [u.pcount], 0
  2860 000056F0 7705                <1> 	ja	short dskw_5
  2861                              <1> dskw_4:
  2862                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2863 000056F2 E810FEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2864                              <1> dskw_5:
  2865                              <1> 	; eBX (r5) = system (I/O) buffer address
  2866 000056F7 E87D000000          <1> 	call	sioreg
  2867                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2868                              <1> 			     ; / r1 = address of data, r2 points to location
  2869                              <1> 			     ; / in buffer in which to start writing data
  2870                              <1> 	; eSI = file (user data) offset
  2871                              <1> 	; eDI = sector (I/O) buffer offset
  2872                              <1> 	; eCX = byte count
  2873                              <1> 	;
  2874 000056FC F3A4                <1>   	rep	movsb
  2875                              <1> 		; movb (r1 )+,(r2)+ 
  2876                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2877                              <1> 		; dec r3 / decrement no. of bytes to be written
  2878                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2879                              <1> 	; 25/07/2015
  2880                              <1> 	; eax = remain bytes in buffer
  2881                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2882 000056FE 09C0                <1> 	or	eax, eax
  2883 00005700 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2884                              <1> dskw_6:
  2885 00005702 E805060000          <1> 	call	dskwr
  2886                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2887 00005707 833D[D06E0000]00    <1>         cmp     dword [u.count], 0
  2888                              <1> 		; tst u.count / any more data to write?
  2889 0000570E 77A4                <1> 	ja	short dskw_1
  2890                              <1> 		; bne 1b / yes, branch
  2891                              <1> 	; 03/08/2013
  2892 00005710 C605[0D6F0000]00    <1> 	mov	byte [u.kcall], 0
  2893                              <1> 	; 20/09/2013 (;;)
  2894                              <1> 	;pop	ax
  2895                              <1> 	; 03/02/2022
  2896 00005717 58                  <1> 	pop	eax
  2897 00005718 C3                  <1> 	retn
  2898                              <1> 	;;jmp 	short dskw_ret 
  2899                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2900                              <1> 
  2901                              <1> cpass: ; / get next character from user area of core and put it in r1
  2902                              <1> 	; 18/10/2015
  2903                              <1> 	; 10/10/2015
  2904                              <1> 	; 10/07/2015
  2905                              <1> 	; 02/07/2015
  2906                              <1> 	; 01/07/2015
  2907                              <1> 	; 24/06/2015
  2908                              <1> 	; 08/06/2015
  2909                              <1> 	; 04/06/2015
  2910                              <1> 	; 20/05/2015
  2911                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2912                              <1> 	;
  2913                              <1> 	; INPUTS -> 
  2914                              <1> 	;     [u.base] = virtual address in user area
  2915                              <1> 	;     [u.count] = byte count (max.)
  2916                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2917                              <1> 	; OUTPUTS -> 
  2918                              <1> 	;     AL = the character which is pointed by [u.base]
  2919                              <1> 	;     zf = 1 -> transfer count has been completed	
  2920                              <1>         ;
  2921                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2922                              <1> 	;
  2923                              <1> 	;
  2924 00005719 833D[D06E0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2925                              <1> 		; tst u.count / have all the characters been transferred
  2926                              <1> 			    ; / (i.e., u.count, # of chars. left
  2927 00005720 763F                <1> 	jna	short cpass_3
  2928                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2929 00005722 FF0D[D06E0000]      <1> 	dec	dword [u.count]
  2930                              <1> 		; dec u.count / no, decrement u.count
  2931                              <1>         ; 19/05/2015 
  2932                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2933                              <1> 	;		      to physical address
  2934 00005728 66833D[0B6F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2935                              <1> 			     ; 1-4095 --> use previous physical base address
  2936                              <1> 			     ; in [u.pbase]
  2937 00005730 770E                <1> 	ja	short cpass_1
  2938                              <1> 	; 02/07/2015
  2939 00005732 833D[036F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2940 00005739 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2941                              <1> 	; 08/06/2015 - 10/07/2015
  2942 0000573B E8C7FDFFFF          <1> 	call	trans_addr_r
  2943                              <1> cpass_1:
  2944                              <1> 	; 02/07/2015
  2945                              <1> 	; 24/06/2015
  2946 00005740 66FF0D[0B6F0000]    <1> 	dec	word [u.pcount]
  2947                              <1> cpass_2: 
  2948                              <1> 	; 10/10/2015
  2949                              <1> 	; 02/07/2015
  2950 00005747 8B15[076F0000]      <1> 	mov	edx, [u.pbase]
  2951 0000574D 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  2952                              <1> 		; movb *u.base,r1 / take the character pointed to 
  2953                              <1> 				; / by u.base and put it in r1
  2954 0000574F FF05[D46E0000]      <1> 	inc	dword [u.nread]
  2955                              <1> 		; inc u.nread / increment no. of bytes transferred
  2956 00005755 FF05[CC6E0000]      <1> 	inc	dword [u.base]
  2957                              <1> 		; inc u.base / increment the buffer address to point to the
  2958                              <1> 			   ; / next byte
  2959 0000575B FF05[076F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2960                              <1> cpass_3:
  2961 00005761 C3                  <1> 	retn
  2962                              <1> 		; rts	r0 / next byte
  2963                              <1> 	; 1: 
  2964                              <1> 		; mov (sp)+,r0 
  2965                              <1> 		         ; / put return address of calling routine into r0
  2966                              <1> 		; mov (sp)+,r1 / i-number in r1
  2967                              <1> 		; rts r0 / non-local return
  2968                              <1> cpass_k:
  2969                              <1> 	; 02/07/2015
  2970                              <1> 	; The caller is os kernel 
  2971                              <1> 	; (get sysexec arguments from kernel's memory space)
  2972                              <1> 	;
  2973 00005762 8B1D[CC6E0000]      <1> 	mov	ebx, [u.base]
  2974 00005768 66C705[0B6F0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  2974 00005770 10                  <1>
  2975 00005771 891D[076F0000]      <1> 	mov	[u.pbase], ebx
  2976 00005777 EBCE                <1> 	jmp	short cpass_2
  2977                              <1> 	
  2978                              <1> sioreg: 
  2979                              <1> 	; 25/07/2015
  2980                              <1> 	; 18/07/2015
  2981                              <1> 	; 02/07/2015
  2982                              <1> 	; 17/06/2015
  2983                              <1> 	; 09/06/2015
  2984                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2985                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  2986                              <1> 	;
  2987                              <1> 	; INPUTS -> 
  2988                              <1> 	;     eBX = system buffer (data) address (r5)
  2989                              <1> 	;     [u.fofp] = pointer to file offset pointer
  2990                              <1> 	;     [u.base] = virtual address of the user buffer
  2991                              <1> 	;     [u.pbase] = physical address of the user buffer
  2992                              <1> 	;     [u.count] = byte count
  2993                              <1> 	;     [u.pcount] = byte count within page frame 			
  2994                              <1> 	; OUTPUTS -> 
  2995                              <1> 	;     eSI = user data offset (r1)
  2996                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  2997                              <1> 	;     eCX = byte count (r3)
  2998                              <1> 	;     EAX = remain bytes after byte count within page frame
  2999                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3000                              <1>         ;
  3001                              <1> 	; ((Modified registers:  EDX))
  3002                              <1>  
  3003 00005779 8B35[BC6E0000]      <1>         mov     esi, [u.fofp]
  3004 0000577F 8B3E                <1>         mov     edi, [esi]
  3005                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3006 00005781 89F9                <1> 	mov	ecx, edi
  3007                              <1> 		; mov r2,r3 / and also to r3
  3008 00005783 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3009                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3010 00005789 81E7FF010000        <1> 	and	edi, 1FFh
  3011                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3012 0000578F 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3013                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3014                              <1> 			  ; / where data is to be placed
  3015                              <1>                 ; mov u.base,r1 / address of data is in r1
  3016 00005791 F7D9                <1> 	neg	ecx
  3017                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3018                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3019 00005793 3B0D[D06E0000]      <1> 	cmp	ecx, [u.count]
  3020                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3021                              <1> 			       ; / to be written to the file
  3022 00005799 7606                <1> 	jna	short sioreg_0
  3023                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3024                              <1> 			 ; / in the file block as the number to be written
  3025 0000579B 8B0D[D06E0000]      <1> 	mov	ecx, [u.count]
  3026                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3027                              <1> 			       ; / bytes as the number to be written
  3028                              <1> sioreg_0:
  3029                              <1> 	; 17/06/2015
  3030 000057A1 803D[0D6F0000]00    <1> 	cmp	byte [u.kcall], 0 
  3031 000057A8 7613                <1> 	jna	short sioreg_1
  3032                              <1> 	; 25/07/2015
  3033                              <1> 	; the caller is 'mkdir' or 'namei'
  3034 000057AA A1[CC6E0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3035 000057AF A3[076F0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3036 000057B4 66890D[0B6F0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3037 000057BB EB0B                <1> 	jmp	short sioreg_2
  3038                              <1> sioreg_1:
  3039                              <1> 	; 25/07/2015
  3040                              <1> 	; 18/07/2015
  3041                              <1> 	; 09/06/2015 
  3042 000057BD 0FB715[0B6F0000]    <1> 	movzx	edx, word [u.pcount]
  3043                              <1> 		; ecx and [u.pcount] are always > 0, here
  3044 000057C4 39D1                <1> 	cmp	ecx, edx	
  3045 000057C6 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3046                              <1> sioreg_2: ; 2:
  3047 000057C8 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3048                              <1> sioreg_3:
  3049 000057CA 010D[D46E0000]      <1> 	add 	[u.nread], ecx
  3050                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3051                              <1> 			         ; / during write is put into u.nread
  3052 000057D0 290D[D06E0000]      <1> 	sub 	[u.count], ecx
  3053                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3054                              <1> 			       ; / must be written or read
  3055 000057D6 010D[CC6E0000]      <1> 	add 	[u.base], ecx
  3056                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3057                              <1> 			      ; / data bytes
  3058 000057DC 010E                <1>         add 	[esi], ecx 
  3059                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3060                              <1> 			       ; / + old file offset
  3061                              <1> 	; 25/07/2015
  3062 000057DE 8B35[076F0000]      <1> 	mov	esi, [u.pbase]
  3063 000057E4 66290D[0B6F0000]    <1> 	sub	[u.pcount], cx
  3064 000057EB 010D[076F0000]      <1> 	add	[u.pbase], ecx
  3065 000057F1 C3                  <1>         retn
  3066                              <1> 		; rts r0
  3067                              <1> 		; transfer count > [u.pcount]
  3068                              <1> sioreg_4:
  3069                              <1> 	; 25/07/2015
  3070                              <1> 	; transfer count > [u.pcount] 
  3071                              <1> 	; (ecx > edx)
  3072 000057F2 89C8                <1> 	mov	eax, ecx
  3073 000057F4 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3074 000057F6 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3075 000057F8 EBD0                <1> 	jmp	short sioreg_3
  2052                                  %include 'u7.s'        ; 18/04/2015
  2053                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  2054                              <1> ; Last Modification: 03/03/2022
  2055                              <1> ; ----------------------------------------------------------------------------
  2056                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2057                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2058                              <1> ;
  2059                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2060                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2061                              <1> ; <Bell Laboratories (17/3/1972)>
  2062                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2063                              <1> ;
  2064                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2065                              <1> ;
  2066                              <1> ; ****************************************************************************
  2067                              <1> ; 14/11/2015
  2068                              <1> 
  2069                              <1> sysmount: ; / mount file system; args special; name
  2070                              <1> 	; 12/02/2022
  2071                              <1> 	; 04/02/2022
  2072                              <1> 	; 14/11/2015
  2073                              <1> 	; 24/10/2015
  2074                              <1> 	; 13/10/2015
  2075                              <1> 	; 10/07/2015
  2076                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2077                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2078                              <1> 	;
  2079                              <1> 	; 'sysmount' anounces to the system that a removable 
  2080                              <1> 	; file system has been mounted on a special file.
  2081                              <1> 	; The device number of the special file is obtained vihha
  2082                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2083                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2084                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2085                              <1> 	; to read file system into core, i.e. the first block on the
  2086                              <1> 	; mountable file system is read in. This block is super block
  2087                              <1> 	; for the file system. This call is super user restricted.	
  2088                              <1> 	;
  2089                              <1> 	; Calling sequence:
  2090                              <1> 	;	sysmount; special; name
  2091                              <1> 	; Arguments:
  2092                              <1> 	;	special - pointer to name of special file (device)
  2093                              <1> 	;	name -  pointer to name of the root directory of the
  2094                              <1> 	;		newly mounted file system. 'name' should 
  2095                              <1> 	;		always be a directory.
  2096                              <1> 	; Inputs: - 
  2097                              <1> 	; Outputs: -
  2098                              <1> 	; ...............................................................
  2099                              <1> 	;				
  2100                              <1> 	; Retro UNIX 8086 v1 modification: 
  2101                              <1> 	;       'sysmount' system call has two arguments; so,
  2102                              <1> 	;	* 1st argument, special is pointed to by BX register
  2103                              <1> 	;	* 2nd argument, name is in CX register
  2104                              <1> 	;
  2105                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2106                              <1> 	;	       already modified for IBM PC compatibility and 
  2107                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2108                              <1> 	
  2109                              <1> 	;call	arg2
  2110                              <1> 		; jsr r0,arg2 / get arguments special and name
  2111 000057FA 891D[C46E0000]      <1> 	mov	[u.namep], ebx
  2112                              <1> 	; 12/02/2022
  2113                              <1> 	;push	ecx ; directory name
  2114 00005800 66833D[966E0000]00  <1> 	cmp	word [mnti], 0
  2115                              <1> 		; tst mnti / is the i-number of the cross device file
  2116                              <1> 			 ; / zero?
  2117                              <1> 	;;ja	error
  2118                              <1>         	; bne errora / no, error
  2119                              <1> 	;ja	sysmnt_err0
  2120                              <1> 	; 04/02/2022
  2121 00005808 7605                <1> 	jna	short sysmnt_0
  2122 0000580A E907010000          <1> 	jmp	sysmnt_err0
  2123                              <1> sysmnt_0:
  2124                              <1> 	; 12/02/2022
  2125 0000580F 51                  <1> 	push	ecx ; directory name
  2126 00005810 E8E9000000          <1> 	call	getspl
  2127                              <1> 		; jsr r0,getspl / get special files device number in r1
  2128                              <1> 	; 12/02/2022
  2129 00005815 8F05[C46E0000]      <1> 	pop	dword [u.namep] ; directory name
  2130                              <1> 	; 13/10/2015
  2131                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2132                              <1> 	; 04/02/2022
  2133 0000581B 29DB                <1> 	sub	ebx, ebx
  2134 0000581D 88C3                <1> 	mov	bl, al
  2135 0000581F F683[2A660000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2136 00005826 750F                <1> 	jnz	short sysmnt_1
  2137                              <1> sysmnt_err1:
  2138 00005828 C705[FB6E0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2138 00005830 0000                <1>
  2139 00005832 E9AFE2FFFF          <1> 	jmp	error
  2140                              <1> sysmnt_1:
  2141                              <1> 	; 12/02/2022
  2142                              <1> 	;pop	dword [u.namep]
  2143                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2144                              <1> 				  ; / on the device
  2145                              <1> 	; 14/11/2015
  2146 00005837 53                  <1> 	push	ebx ; 13/10/2015
  2147                              <1> 		; mov r1,-(sp) / save the device number
  2148                              <1>         ;
  2149 00005838 E89BF1FFFF          <1> 	call	namei
  2150                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2151                              <1> 		       ; ax = 0 -> file not found 	
  2152                              <1> 	;jz	error
  2153                              <1> 	;jc	error
  2154                              <1> 		; jsr r0,namei / get the i-number of the file
  2155                              <1>                	; br errora
  2156 0000583D 730F                <1> 	jnc	short sysmnt_2
  2157                              <1> sysmnt_err2:
  2158 0000583F C705[FB6E0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2158 00005847 0000                <1>
  2159 00005849 E998E2FFFF          <1> 	jmp	error
  2160                              <1> sysmnt_2:	
  2161 0000584E 66A3[966E0000]      <1> 	mov	[mnti], ax
  2162                              <1>         	; mov r1,mnti / put it in mnti
  2163                              <1> 	; 04/02/2022
  2164 00005854 BB[647D0000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2165                              <1> sysmnt_3: ;1:
  2166                              <1>         ;cmp	byte [ebx+1], 0
  2167                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2168                              <1> 			   ; / dismountable device set?
  2169                              <1>         ;jna	short sysmnt_4		
  2170                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2171                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2172                              <1> 	;jmp	short sysmnt_3
  2173                              <1> sysmnt_4:   
  2174 00005859 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2175 0000585A A2[936E0000]        <1> 	mov	[mdev], al
  2176                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2177 0000585F 8803                <1> 	mov	[ebx], al
  2178                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2179                              <1> 			      ; / of the I/O queue entry
  2180                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2181                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2182 00005861 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2183                              <1> 		; bis $2000,sb1 / set the read bit
  2184                              <1> 	; Retro UNIX 386 v1 modification : 
  2185                              <1> 	;	32 bit block number at buffer header offset 4
  2186 00005866 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2187 0000586D E8E5050000          <1> 	call 	diskio
  2188 00005872 7345                <1> 	jnc	short sysmnt_5
  2189 00005874 31C0                <1> 	xor 	eax, eax
  2190 00005876 66A3[966E0000]      <1> 	mov	[mnti], ax ; 0
  2191 0000587C A2[936E0000]        <1> 	mov	[mdev], al ; 0
  2192                              <1> 	;mov	[cdev], al ; 0
  2193                              <1> 	; 12/02/2022
  2194 00005881 803D[0E6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2195 00005888 7508                <1> 	jne	short sysmnt_err3
  2196                              <1> 	; yes, clear [u.brwdev] for next check
  2197                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2198 0000588A FE05[0E6F0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2199 00005890 EB0A                <1> 	jmp	short sysmnt_err4
  2200                              <1> sysmnt_err3:	; 12/02/2022
  2201                              <1> 	; no, set [u.error] to disk read error
  2202 00005892 C705[FB6E0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2202 0000589A 0000                <1>
  2203                              <1> sysmnt_err4:
  2204                              <1> 	; 12/02/2022
  2205                              <1> 	; 14/11/2015
  2206 0000589C FEC8                <1> 	dec 	al
  2207 0000589E 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2208 000058A0 FEC0                <1> 	inc	al
  2209 000058A2 48                  <1> 	dec	eax
  2210 000058A3 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2211 000058A6 E93BE2FFFF          <1> 	jmp	error
  2212                              <1> sysmnt_invd:
  2213                              <1> 	; 12/02/2022
  2214 000058AB C705[FB6E0000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2214 000058B3 0000                <1>
  2215                              <1> 				 ;'invalid fs/superblock !' error
  2216 000058B5 30C0                <1> 	xor	al, al
  2217 000058B7 EBE3                <1> 	jmp	short sysmnt_err4
  2218                              <1> 
  2219                              <1> sysmnt_5:
  2220                              <1> 	; 04/02/2022 (BugFix)
  2221                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2222                              <1> 	; (Following check is needed to prevent mounting an
  2223                              <1> 	; invalid valid file system (invalid super block).
  2224                              <1> 	; 
  2225 000058B9 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2226 000058BC C0E002              <1> 	shl	al, 2 ; 4*index
  2227 000058BF 8B88[0E660000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2228                              <1> 	;;shl 	ecx, 3 ; !!!
  2229                              <1> 	; 04/02/2022
  2230 000058C5 C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2231                              <1> 	; ecx = number of free map bytes (required)
  2232                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2233 000058C8 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2234                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2235                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2236 000058CC 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2237                              <1> 			 ; (in sectors), if they are not equal
  2238                              <1> 			 ; the disk to be mounted is an...	
  2239 000058CE 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2240                              <1> 			 ; (which has not got a valid super block)
  2241                              <1> 	;
  2242 000058D0 C6430100            <1> 	mov	byte [ebx+1], 0
  2243                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2244                              <1> ;sysmnt_6: ;1:
  2245                              <1> 	;;cmp	byte [sb1+1], 0
  2246                              <1> 		; tstb sb1+1 / done reading?
  2247                              <1>    	;;jna	sysret
  2248                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2249                              <1> 	;;jmp	short sysmnt_6
  2250                              <1> 		;bne 1b / no, wait
  2251                              <1>         	;br sysreta / yes
  2252 000058D4 E92DE2FFFF          <1> 	jmp	sysret
  2253                              <1> 
  2254                              <1> sysumount: ; / special dismount file system
  2255                              <1> 	; 04/02/2022
  2256                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2257                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2258                              <1> 	;
  2259                              <1> 	; 04/11/2013
  2260                              <1> 	; 09/07/2013
  2261                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2262                              <1> 	; indicated as an argument is no longer contain a removable
  2263                              <1> 	; file system. 'getspl' gets the device number of the special
  2264                              <1> 	; file. If no file system was mounted on that device an error
  2265                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2266                              <1> 	; to 'sysret'.
  2267                              <1> 	;
  2268                              <1> 	; Calling sequence:
  2269                              <1> 	;	sysmount; special
  2270                              <1> 	; Arguments:
  2271                              <1> 	;	special - special file to dismount (device)
  2272                              <1> 	;
  2273                              <1> 	; Inputs: - 
  2274                              <1> 	; Outputs: -
  2275                              <1> 	; ...............................................................
  2276                              <1> 	;				
  2277                              <1> 	; Retro UNIX 8086 v1 modification: 
  2278                              <1> 	;       'sysumount' system call has one argument; so,
  2279                              <1> 	;	* Single argument, special is pointed to by BX register
  2280                              <1> 	;
  2281                              <1> 	
  2282                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2283                              <1> 	;call	arg
  2284                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2285 000058D9 891D[C46E0000]      <1>         mov	[u.namep], ebx
  2286 000058DF E81A000000          <1> 	call	getspl
  2287                              <1> 		; jsr r0,getspl / get the device number in r1
  2288 000058E4 3A05[936E0000]      <1> 	cmp	al, [mdev]
  2289                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2290 000058EA 752A                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2291                              <1> 	;jne	error
  2292                              <1>         	; bne errora / no error
  2293 000058EC 30C0                <1> 	xor	al, al ; ah = 0
  2294                              <1> sysumnt_0: ;1:
  2295                              <1>      	; 04/02/2022
  2296                              <1> 	;cmp 	[sb1+1], al ; 0
  2297                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2298                              <1> 	;		   ; / (inhibit bit set)?
  2299                              <1> 	;jna	short sysumnt_1		
  2300                              <1> 	;	; bne 1b / yes, wait
  2301                              <1> 	;call	idle ; (wait for hardware interrupt)
  2302                              <1> 	;jmp	short sysumnt_0
  2303                              <1> sysumnt_1:        
  2304 000058EE A2[936E0000]        <1> 	mov	[mdev], al
  2305                              <1> 	     	; clr mntd / no, clear these
  2306 000058F3 66A3[966E0000]      <1>    	mov	[mnti], ax
  2307                              <1>         	; clr mnti
  2308 000058F9 E908E2FFFF          <1>         jmp	sysret
  2309                              <1> 		; br sysreta / return
  2310                              <1> 
  2311                              <1> getspl: ; / get device number from a special file name
  2312 000058FE E8D5F0FFFF          <1> 	call	namei
  2313                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2314                              <1> 		       ; ax = 0 -> file not found 	
  2315                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2316                              <1> 	; 04/02/2022
  2317 00005903 7305                <1> 	jnc	short getspl_0
  2318 00005905 E935FFFFFF          <1> 	jmp	sysmnt_err2
  2319                              <1> getspl_0:
  2320                              <1> 	;jz	error
  2321                              <1> 	;jc	error
  2322                              <1> 		; jsr r0,namei / get the i-number of the special file
  2323                              <1>                 ; br errora / no such file
  2324 0000590A 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2325                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2326                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2327 0000590E 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2328                              <1> 	;jc	error
  2329                              <1> 		; ble errora / less than 0?  yes, error
  2330 00005910 6683F805            <1>         cmp	ax, 5 ;
  2331                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2332                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2333                              <1> 	;;ja	error
  2334                              <1>         ;	; bgt errora / yes, error
  2335                              <1>         ; 04/02/2022
  2336 00005914 760F                <1> 	jna	short getspl_retn
  2337                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2338                              <1> ;iopen_retn:
  2339                              <1> ;	retn
  2340                              <1> 		; rts r0 / return with device number in r1
  2341                              <1> sysmnt_err0:
  2342 00005916 C705[FB6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2342 0000591E 0000                <1>
  2343 00005920 E9C1E1FFFF          <1> 	jmp	error
  2344                              <1> 
  2345                              <1> getspl_retn:
  2346                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2347                              <1> 	; 04/02/2022
  2348                              <1> iopen_retn:
  2349 00005925 C3                  <1> 	retn
  2350                              <1> 
  2351                              <1> iopen:
  2352                              <1> 	; 04/02/2022
  2353                              <1> 	; 19/05/2015
  2354                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2355                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2356                              <1> 	;
  2357                              <1> 	; open file whose i-number is in r1
  2358                              <1> 	; 
  2359                              <1> 	; INPUTS ->
  2360                              <1> 	;    r1 - inode number
  2361                              <1> 	; OUTPUTS ->
  2362                              <1> 	;    file's inode in core	
  2363                              <1> 	;    r1 - inode number (positive)
  2364                              <1> 	;
  2365                              <1> 	; ((AX = R1))
  2366                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2367                              <1> 	;        
  2368                              <1> ; / open file whose i-number is in r1
  2369 00005926 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2370                              <1> 		; tst r1 / write or read access?
  2371 00005929 7568                <1>         jnz	short iopen_2
  2372                              <1> 		; blt 2f / write, go to 2f
  2373 0000592B B202                <1> 	mov	dl, 2 ; read access
  2374 0000592D E844F9FFFF          <1> 	call	access
  2375                              <1>         	; jsr r0,access; 2 
  2376                              <1> 	; / get inode into core with read access
  2377                              <1> 	; DL=2
  2378                              <1> iopen_0:
  2379 00005932 6683F828            <1>         cmp	ax, 40
  2380                              <1> 		; cmp r1,$40. / is it a special file
  2381 00005936 77ED                <1>         ja	short iopen_retn
  2382                              <1> 		; bgt 3f / no. 3f
  2383                              <1> 	; 04/02/2022
  2384 00005938 50                  <1> 	push	eax
  2385                              <1> 	;push	ax
  2386                              <1> 		; mov r1,-(sp) / yes, figure out
  2387 00005939 0FB6D8              <1> 	movzx	ebx, al
  2388 0000593C C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2389                              <1> 	;shl	bx, 2
  2390                              <1> 		; asl r1
  2391 0000593F 81C3[43590000]      <1>         add     ebx, iopen_1 - 4
  2392 00005945 FF23                <1> 	jmp	dword [ebx]
  2393                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2394                              <1> iopen_1: ; 1:
  2395 00005947 [AB590000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2396                              <1>  		 ;otty / tty ; r1=2
  2397                              <1>         	 ;oppt / ppt ; r1=4
  2398 0000594B [635A0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2399                              <1> 		 ;sret / mem ; r1=6
  2400                              <1> 		 ;sret / rf0
  2401                              <1>         	 ;sret / rk0
  2402                              <1>         	 ;sret / tap0
  2403                              <1>         	 ;sret / tap1
  2404                              <1>         	 ;sret / tap2
  2405                              <1>         	 ;sret / tap3
  2406                              <1>         	 ;sret / tap4
  2407                              <1>         	 ;sret / tap5
  2408                              <1>         	 ;sret / tap6
  2409                              <1>         	 ;sret / tap7
  2410 0000594F [635A0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2411 00005953 [635A0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2412 00005957 [635A0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2413 0000595B [635A0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2414 0000595F [635A0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2415 00005963 [635A0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2416                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2417 00005967 [635A0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2418 0000596B [BC590000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2419                              <1> 		 ;ocvt / tty0
  2420 0000596F [BC590000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2421                              <1> 		 ;ocvt / tty1
  2422 00005973 [BC590000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2423                              <1> 		 ;ocvt / tty2
  2424 00005977 [BC590000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2425                              <1> 		 ;ocvt / tty3
  2426 0000597B [BC590000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2427                              <1> 		 ;ocvt / tty4
  2428 0000597F [BC590000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2429                              <1> 		 ;ocvt / tty5
  2430 00005983 [BC590000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2431                              <1> 		 ;ocvt / tty6
  2432 00005987 [BC590000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2433                              <1> 		 ;ocvt / tty7
  2434 0000598B [BC590000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2435                              <1> 		 ;error / crd
  2436 0000598F [BC590000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2437                              <1> 
  2438                              <1> iopen_2: ; 2: / check open write access
  2439 00005993 66F7D8              <1> 	neg	ax
  2440                              <1> 		; neg r1 / make inode number positive
  2441 00005996 B201                <1> 	mov	dl, 1 ; write access
  2442 00005998 E8D9F8FFFF          <1> 	call	access
  2443                              <1> 		; jsr r0,access; 1 / get inode in core
  2444                              <1> 	; DL=1
  2445                              <1> 	; 04/02/2022
  2446 0000599D F605[A96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2447                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2448                              <1>  		; bit $40000,i.flgs / is it a directory?
  2449 000059A4 748C                <1> 	jz	short iopen_0
  2450                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2451                              <1> 	;jmp	error ; permission denied !
  2452 000059A6 E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2453                              <1> 	;;jnz	error		
  2454                              <1>        		; bne 2f / yes, transfer (error)
  2455                              <1>         ;;jmp	short iopen_0
  2456                              <1> 	;cmp	ax, 40
  2457                              <1> 		; cmp r1,$40. / no, is it a special file?
  2458                              <1>         ;ja	short iopen_2
  2459                              <1> 		; bgt 3f / no, return
  2460                              <1> 	;push	ax
  2461                              <1> 		; mov r1,-(sp) / yes
  2462                              <1> 	;movzx	ebx, al
  2463                              <1> 	;shl	bx, 1
  2464                              <1> 		; asl r1
  2465                              <1> 	;add	ebx, ipen_3 - 2
  2466                              <1> 	;jmp	dword [ebx]
  2467                              <1> 		; jmp *1f-2(r1) / figure out 
  2468                              <1> 			; / which special file it is and transfer
  2469                              <1> ;iopen_3: ; 1:
  2470                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2471                              <1>  		 ;otty / tty ; r1=2
  2472                              <1>         	 ;leadr / ppt ; r1=4
  2473                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2474                              <1> 		 ;sret / mem ; r1=6
  2475                              <1> 		 ;sret / rf0
  2476                              <1>         	 ;sret / rk0
  2477                              <1>         	 ;sret / tap0
  2478                              <1>         	 ;sret / tap1
  2479                              <1>         	 ;sret / tap2
  2480                              <1>         	 ;sret / tap3
  2481                              <1>         	 ;sret / tap4
  2482                              <1>         	 ;sret / tap5
  2483                              <1>         	 ;sret / tap6
  2484                              <1>         	 ;sret / tap7
  2485                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2486                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2487                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2488                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2489                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2490                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2491                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2492                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2493                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2494                              <1> 		 ;ocvt / tty0
  2495                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2496                              <1> 		 ;ocvt / tty1
  2497                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2498                              <1> 		 ;ocvt / tty2
  2499                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2500                              <1> 		 ;ocvt / tty3
  2501                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2502                              <1> 		 ;ocvt / tty4
  2503                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2504                              <1> 		 ;ocvt / tty5
  2505                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2506                              <1> 		 ;ocvt / tty6
  2507                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2508                              <1> 		 ;ocvt / tty7
  2509                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2510                              <1> 		 ;/ ejec / lpr
  2511                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2512                              <1> 
  2513                              <1> otty: ;/ open console tty for reading or writing
  2514                              <1> 	; 03/03/2022
  2515                              <1> 	; 02/03/2022
  2516                              <1> 	; 27/02/2022
  2517                              <1> 	; 23/02/2022
  2518                              <1> 	; 22/02/2022
  2519                              <1> 	; 04/02/2022
  2520                              <1> 	; 16/11/2015
  2521                              <1> 	; 12/11/2015
  2522                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2523                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2524                              <1> 	; 16/07/2013
  2525                              <1> 	; Retro UNIX 8086 v1 modification:
  2526                              <1> 	;  If a tty is open for read or write by
  2527                              <1> 	;     a process (u.uno), only same process can open
  2528                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2529                              <1> 	;
  2530                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2531                              <1> 	;
  2532 000059AB 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2533 000059B2 8A83[076C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2534                              <1> 	; 13/01/2014
  2535                              <1> 	;jmp	short ottyp
  2536                              <1> 	; 23/02/2022
  2537 000059B8 88C4                <1> 	mov	ah, al
  2538 000059BA EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2539                              <1> ocvt:
  2540 000059BC 2C0A                <1> 	sub	al, 10
  2541                              <1> 	; 04/02/2022
  2542 000059BE 31DB                <1> 	xor	ebx, ebx
  2543                              <1> ottyp:
  2544                              <1> 	; 23/02/2022
  2545 000059C0 B4FF                <1> 	mov	ah, 0FFh
  2546                              <1> ottypc:
  2547                              <1> 	; 03/03/2022
  2548                              <1> 	; 23/02/2022
  2549                              <1> 	; 22/02/2022
  2550                              <1> 	; 12/02/2022
  2551                              <1> 	; 04/02/2022
  2552                              <1> 	; 16/11/2015
  2553                              <1> 	; 12/11/2015
  2554                              <1> 	; 18/05/2015 (32 bit modifications)
  2555                              <1> 	; 06/12/2013 - 13/07/2014
  2556 000059C2 88C6                <1> 	mov	dh, al ; tty number
  2557                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2558                              <1> 	; 04/02/2022
  2559 000059C4 88C3                <1> 	mov	bl, al
  2560 000059C6 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2561                              <1> 	; 26/01/2014	
  2562 000059C8 81C3[346B0000]      <1> 	add 	ebx, ttyl
  2563 000059CE 668B0B              <1> 	mov 	cx, [ebx]
  2564                              <1> 		   ; CL = lock value (0 or process number)
  2565                              <1> 		   ; CH = open count 
  2566 000059D1 20C9                <1> 	and 	cl, cl
  2567                              <1> 	; 13/01/2014
  2568                              <1> 	;jz 	short otty_ret
  2569                              <1> 	; 04/02/2022
  2570 000059D3 7447                <1> 	jz 	short ottys_0
  2571                              <1> 	;
  2572                              <1> 	; 16/11/2015
  2573 000059D5 3A0D[F56E0000]      <1> 	cmp 	cl, [u.uno]
  2574 000059DB 746E                <1> 	je	short ottys_3
  2575                              <1> 	;
  2576                              <1> 	; 23/02/2022
  2577                              <1> 	; (is it the console tty of the current process?)
  2578                              <1> 	; ((fast check/permit for console tty open function))
  2579 000059DD 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2580 000059DF 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2581                              <1> 	;
  2582                              <1> 	; 22/02/2022
  2583                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2584                              <1> 	;shl 	bl, 1
  2585                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2586                              <1> 	;;movzx ebx, byte [u.uno]
  2587                              <1> 	;mov	bl, [u.uno]
  2588                              <1> 	;shl 	bl, 1
  2589                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2590                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2591                              <1> 	; 22/02/2022 (BugFix) ; *
  2592 000059E1 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2593 000059E4 D1E6                <1> 	shl 	esi, 1
  2594 000059E6 668B86[C66B0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2595 000059ED 96                  <1> 	xchg	esi, eax
  2596 000059EE A0[F56E0000]        <1> 	mov	al, [u.uno]
  2597 000059F3 D0E0                <1> 	shl 	al, 1
  2598 000059F5 663BB0[E66B0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2599 000059FC 744D                <1> 	je 	short ottys_3 ; *
  2600                              <1> 	; 23/02/2022
  2601                              <1> 	; check console tty of the process
  2602                              <1> 	; (open permission must be given if the -requested- tty is
  2603                              <1> 	;  console tty of current process)
  2604 000059FE D0E8                <1> 	shr	al, 1
  2605 00005A00 38B0[076C0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2606 00005A06 7443                <1> 	je 	short ottys_3
  2607                              <1> 	;
  2608                              <1> 	; the tty is locked by another process
  2609                              <1> 	; except the parent process (p.ppid)
  2610                              <1>         ;
  2611                              <1> 	; 09/02/2022
  2612                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2613                              <1> 	;		; permission denied ! error
  2614                              <1> otty_err: ; 13/01/2014
  2615                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2616                              <1> 	;;jnz	error
  2617                              <1> 	; 04/02/2022
  2618                              <1> 	;jz	short otty_stc_retn
  2619                              <1> 	;jmp	error
  2620                              <1> 	; 12/02/2022
  2621 00005A08 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2622 00005A0B 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2623                              <1> 	; iopen (dl=1 or dl=2)
  2624 00005A0D C705[FB6E0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2624 00005A15 0000                <1>
  2625                              <1> 			; permission denied ! error
  2626 00005A17 E9CAE0FFFF          <1> 	jmp	error
  2627                              <1> ;otty_stc_retn:
  2628                              <1> 	;stc
  2629                              <1> 	;retn
  2630                              <1> ottys_0:
  2631                              <1> 	; 04/02/2022
  2632                              <1> otty_ret: 
  2633                              <1> 	; 13/01/2014
  2634 00005A1C 80FE07              <1> 	cmp 	dh, 7
  2635 00005A1F 7624                <1> 	jna	short ottys_2
  2636                              <1> 	; 16/11/2015
  2637                              <1> com_port_check:
  2638 00005A21 BE[526B0000]        <1> 	mov	esi, com1p
  2639 00005A26 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2640 00005A29 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2641 00005A2B 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2642                              <1> ottys_1:
  2643                              <1> 	; 12/11/2015
  2644 00005A2C 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2645 00005A2F 7714                <1> 	ja	short com_port_ready
  2646                              <1> 	;
  2647                              <1> 	; 12/02/2022
  2648 00005A31 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2649 00005A34 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2650 00005A36 C705[FB6E0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2650 00005A3E 0000                <1>
  2651                              <1> 			   ; device not ready ! error
  2652                              <1> 	;jmp	short otty_err
  2653 00005A40 E9A1E0FFFF          <1> 	jmp	error
  2654                              <1> com_port_ready:
  2655                              <1> ottys_2:
  2656                              <1> 	; 02/03/2022
  2657                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2658                              <1> 	;jnz	short ottys_3
  2659 00005A45 8A0D[F56E0000]      <1> 	mov	cl, [u.uno]
  2660                              <1> ottys_3:
  2661 00005A4B FEC5                <1> 	inc 	ch
  2662 00005A4D 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2663                              <1> 	; 06/12/2013
  2664 00005A50 FEC6                <1> 	inc	dh	; tty number + 1
  2665 00005A52 BB[DC6E0000]        <1> 	mov	ebx, u.ttyp
  2666                              <1> 	; 13/01/2014
  2667 00005A57 F6C202              <1> 	test	dl, 2	; open for read sign
  2668 00005A5A 7501                <1> 	jnz	short ottys_4
  2669 00005A5C 43                  <1> 	inc	ebx
  2670                              <1> ottys_4:
  2671                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2672 00005A5D 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2673                              <1> 	; 27/02/2022
  2674 00005A5F 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2675 00005A61 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2676                              <1> sret:
  2677                              <1> 	;pop 	ax
  2678                              <1> 	; 04/02/2022
  2679 00005A63 58                  <1> 	pop	eax
  2680                              <1> otty_retn:	; 12/02/2022
  2681                              <1> iclose_retn:	
  2682 00005A64 C3                  <1> 	retn
  2683                              <1> 
  2684                              <1> 	;
  2685                              <1> 	; Original UNIX v1 'otty' routine:
  2686                              <1> 	;	
  2687                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2688                              <1>         ;                 / reader status reg
  2689                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2690                              <1>         ;                 / punch status reg
  2691                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2692                              <1>         ;                          / console tty buffer
  2693                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2694                              <1>         ;            / console tty
  2695                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2696                              <1>         ;             / buffer header
  2697                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2698                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2699                              <1>         ;                 / tty
  2700                              <1>         ;br     sret / ?
  2701                              <1> ;sret:
  2702                              <1> 		; clr *$ps / set processor priority to zero
  2703                              <1> ;	pop	ax
  2704                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2705                              <1> ;3:
  2706                              <1> ;	retn
  2707                              <1>         	; rts r0
  2708                              <1> 	
  2709                              <1> ;ocvt:	; < open tty >
  2710                              <1> 	; 13/01/2014
  2711                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2712                              <1> 	; 24/09/2013 consistency check -> ok
  2713                              <1> 	; 16/09/2013
  2714                              <1> 	; 03/09/2013
  2715                              <1> 	; 27/08/2013
  2716                              <1> 	; 16/08/2013
  2717                              <1> 	; 16/07/2013
  2718                              <1> 	; 27/05/2013
  2719                              <1> 	; 21/05/2013
  2720                              <1> 	;
  2721                              <1> 	; Retro UNIX 8086 v1 modification !
  2722                              <1> 	; 
  2723                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2724                              <1> 	;		(exactly different than this one)
  2725                              <1> 	;	was in 'u9.s' file.
  2726                              <1> 	;
  2727                              <1> 	; 16/07/2013
  2728                              <1> 	; Retro UNIX 8086 v1 modification:
  2729                              <1> 	;  If a tty is open for read or write by
  2730                              <1> 	;     a process (u.uno), only same process can open
  2731                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2732                              <1> 	;
  2733                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2734                              <1> 
  2735                              <1> 	; 16/09/2013
  2736                              <1> 	; sub 	al, 10
  2737                              <1> 	
  2738                              <1> 	; 06/12/2013
  2739                              <1> 	;cmp	al, 7
  2740                              <1>         ;jna     short ottyp
  2741                              <1> 	; 13/01/2014
  2742                              <1> 	;jmp	short ottyp
  2743                              <1> 
  2744                              <1> 
  2745                              <1> ;oppt: / open paper tape for reading or writing
  2746                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2747                              <1> ;        tstb   pptiflg / is file already open
  2748                              <1> ;        bne    2f / yes, branch
  2749                              <1> ;1:
  2750                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2751                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2752                              <1> ;               br .+4 / for paper tape input and place in free list
  2753                              <1> ;        br     1b
  2754                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2755                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2756                              <1> ;        br     sret
  2757                              <1> ;2:
  2758                              <1> ;        jmp    error / file already open
  2759                              <1> 
  2760                              <1> iclose: 
  2761                              <1> 	; 04/02/2022
  2762                              <1> 	; 19/05/2015
  2763                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2764                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2765                              <1> 	;
  2766                              <1> 	; close file whose i-number is in r1
  2767                              <1> 	; 
  2768                              <1> 	; INPUTS ->
  2769                              <1> 	;    r1 - inode number
  2770                              <1> 	; OUTPUTS ->
  2771                              <1> 	;    file's inode in core	
  2772                              <1> 	;    r1 - inode number (positive)
  2773                              <1> 	;
  2774                              <1> 	; ((AX = R1))
  2775                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2776                              <1> 	;        
  2777                              <1> ;/ close file whose i-number is in r1
  2778 00005A65 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2779 00005A67 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2780                              <1> 		; tst r1 / test i-number
  2781                              <1>         ;jnz	short iclose_2
  2782                              <1> 		; blt 2f / if neg., branch
  2783 00005A6A 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2784                              <1> 	; 16/07/2013 
  2785 00005A6C 66F7D8              <1> 	neg	ax ; make it positive
  2786                              <1> 	; 12/01/2014
  2787 00005A6F FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2788                              <1> iclose_0:
  2789 00005A71 6683F828            <1> 	cmp	ax, 40
  2790                              <1> 		; cmp r1,$40. / is it a special file
  2791 00005A75 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2792                              <1> 		; bgt 3b / no, return
  2793                              <1> 	; 12/01/2014
  2794                              <1> 	; DL=2 -> special file was opened for reading
  2795                              <1> 	; DL=1 -> special file was opened for writing
  2796                              <1> 	; 04/02/2022
  2797 00005A77 50                  <1> 	push	eax
  2798                              <1> 	;push	ax
  2799                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2800 00005A78 0FB6D8              <1> 	movzx	ebx, al
  2801                              <1> 	; 04/02/2022
  2802 00005A7B C0E302              <1> 	shl	bl, 2
  2803                              <1> 	;shl	bx, 2
  2804                              <1> 		; asl r1
  2805 00005A7E 81C3[825A0000]      <1> 	add	ebx, iclose_1 - 4
  2806 00005A84 FF23                <1> 	jmp	dword [ebx]
  2807                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2808                              <1> iclose_1 :
  2809 00005A86 [D25A0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2810 00005A8A [2D5B0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2811 00005A8E [2D5B0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2812 00005A92 [2D5B0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2813 00005A96 [2D5B0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2814 00005A9A [2D5B0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2815 00005A9E [2D5B0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2816 00005AA2 [2D5B0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2817 00005AA6 [2D5B0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2818                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2819                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2820 00005AAA [E15A0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2821 00005AAE [E15A0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2822 00005AB2 [E15A0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2823 00005AB6 [E15A0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2824 00005ABA [E15A0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2825 00005ABE [E15A0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2826 00005AC2 [E15A0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2827 00005AC6 [E15A0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2828 00005ACA [E15A0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2829 00005ACE [E15A0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2830                              <1> 
  2831                              <1> 	; 1:
  2832                              <1> 	;        ctty   / tty
  2833                              <1> 	;        cppt   / ppt
  2834                              <1> 	;        sret   / mem
  2835                              <1> 	;        sret   / rf0
  2836                              <1> 	;        sret   / rk0
  2837                              <1> 	;        sret   / tap0
  2838                              <1> 	;        sret   / tap1
  2839                              <1> 	;        sret   / tap2
  2840                              <1> 	;        sret   / tap3
  2841                              <1> 	;        sret   / tap4
  2842                              <1> 	;        sret   / tap5
  2843                              <1> 	;        sret   / tap6
  2844                              <1> 	;        sret   / tap7
  2845                              <1> 	;        ccvt   / tty0
  2846                              <1> 	;        ccvt   / tty1
  2847                              <1> 	;        ccvt   / tty2
  2848                              <1> 	;        ccvt   / tty3
  2849                              <1> 	;        ccvt   / tty4
  2850                              <1> 	;        ccvt   / tty5
  2851                              <1> 	;        ccvt   / tty6
  2852                              <1> 	;        ccvt   / tty7
  2853                              <1> 	;        error / crd
  2854                              <1> 
  2855                              <1> ;iclose_2: ; 2: / negative i-number
  2856                              <1> 	;neg	ax
  2857                              <1> 		;neg r1 / make it positive
  2858                              <1> 	;cmp	ax, 40
  2859                              <1> 		;cmp r1,$40. / is it a special file?
  2860                              <1>         ;ja	short @b
  2861                              <1> 		;bgt    3b / no. return
  2862                              <1> 	;push	ax
  2863                              <1> 		;mov r1,-(sp)
  2864                              <1> 	;movzx	ebx, al
  2865                              <1> 	;shl	bx, 1
  2866                              <1> 		;asl r1 / yes. compute jump address and transfer
  2867                              <1> 	;add	ebx, iclose_3 - 2
  2868                              <1> 	;jmp	dword [ebx]
  2869                              <1> 		;jmp *1f-2(r1) / figure out 
  2870                              <1> ;iclose_3:
  2871                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2872                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2873                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2874                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2875                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2876                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2877                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2878                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2879                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2880                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2881                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2882                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2883                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2884                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2885                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2886                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2887                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2888                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2889                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2890                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2891                              <1> 	
  2892                              <1> 	;1:
  2893                              <1> 	;      	ctty   / tty
  2894                              <1> 	;       leadr  / ppt
  2895                              <1> 	;       sret   / mem
  2896                              <1> 	;       sret   / rf0
  2897                              <1> 	;       sret   / rk0
  2898                              <1> 	;       sret   / tap0
  2899                              <1> 	;       sret   / tap1
  2900                              <1> 	;       sret   / tap2
  2901                              <1> 	;       sret   / tap3
  2902                              <1> 	;       sret   / tap4
  2903                              <1> 	;       sret   / tap5
  2904                              <1> 	;       sret   / tap6
  2905                              <1> 	;       sret   / tap7
  2906                              <1> 	;       ccvt   / tty0
  2907                              <1> 	;       ccvt   / tty1
  2908                              <1> 	;       ccvt   / tty2
  2909                              <1> 	;       ccvt   / tty3
  2910                              <1> 	;       ccvt   / tty4
  2911                              <1> 	;       ccvt   / tty5
  2912                              <1> 	;       ccvt   / tty6
  2913                              <1> 	;       ccvt   / tty7
  2914                              <1> 	;/       ejec / lpr
  2915                              <1> 
  2916                              <1> ctty: ; / close console tty
  2917                              <1> 	; 25/02/2022
  2918                              <1> 	; 12/02/2022
  2919                              <1> 	; 05/02/2022
  2920                              <1> 	; 04/02/2022
  2921                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2922                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2923                              <1> 	;
  2924                              <1> 	; Retro UNIX 8086 v1 modification !
  2925                              <1> 	; (DL = 2 -> it is open for reading)
  2926                              <1> 	; (DL = 1 -> it is open for writing)
  2927                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2928                              <1> 	;
  2929                              <1> 	; 06/12/2013
  2930 00005AD2 0FB61D[F56E0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2931 00005AD9 8A83[076C0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2932                              <1> 	; 13/01/2014
  2933                              <1> 	;jmp	short cttyp
  2934                              <1> 	; 05/02/2022
  2935 00005ADF EB04                <1> 	jmp	short ctty_0
  2936                              <1> ccvt:
  2937 00005AE1 2C0A                <1> 	sub 	al, 10
  2938                              <1> cttyp:	; (call from sysstty)
  2939                              <1> 	; 08/01/2022
  2940 00005AE3 31DB                <1> 	xor	ebx, ebx
  2941                              <1> ctty_0:	
  2942                              <1> 	; 18/05/2015 (32 bit modifications)
  2943                              <1> 	; 16/08/2013 - 26/01/2014
  2944                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  2945                              <1> 	; 04/02/2022
  2946 00005AE5 88C3                <1> 	mov	bl, al
  2947 00005AE7 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  2948                              <1> 	; 26/01/2014
  2949 00005AE9 81C3[346B0000]      <1> 	add 	ebx, ttyl
  2950 00005AEF 88C6                <1> 	mov 	dh, al ; tty number
  2951 00005AF1 668B03              <1> 	mov 	ax, [ebx]
  2952                              <1> 		   ; AL = lock value (0 or process number)
  2953                              <1> 		   ; AH = open count 
  2954 00005AF4 20E4                <1> 	and 	ah, ah
  2955 00005AF6 7514                <1> 	jnz	short ctty_ret
  2956                              <1>   	; 12/02/2022
  2957 00005AF8 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  2958 00005AFB 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  2959                              <1> 	; iclose (dl=1 or dl=2)
  2960 00005AFD C705[FB6E0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  2960 00005B05 0000                <1>
  2961                              <1> 			; device not open ! error
  2962                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  2963 00005B07 E9DADFFFFF          <1> 	jmp	error
  2964                              <1> 	; 26/01/2014
  2965                              <1> ctty_ret:
  2966 00005B0C FECC                <1> 	dec 	ah ; decrease open count
  2967 00005B0E 7502                <1> 	jnz	short ctty_1
  2968 00005B10 30C0                <1> 	xor	al, al ; unlock/free tty
  2969                              <1> ctty_1:
  2970 00005B12 668903              <1> 	mov 	[ebx], ax ; close tty instance
  2971                              <1> 	;
  2972 00005B15 BB[DC6E0000]        <1> 	mov	ebx, u.ttyp
  2973                              <1> 	;test	dl, 1 ; open for write sign
  2974                              <1> 	;jz	short ctty_2
  2975                              <1> 	; 25/02/2022
  2976 00005B1A F6C202              <1> 	test	dl, 2 ; open for read sign
  2977 00005B1D 7501                <1> 	jnz	short ctty_2
  2978 00005B1F 43                  <1> 	inc	ebx
  2979                              <1> ctty_2:
  2980 00005B20 FEC6                <1> 	inc	dh ; tty number + 1
  2981 00005B22 3A33                <1> 	cmp	dh, [ebx]
  2982                              <1> 	;jne	short cret
  2983 00005B24 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  2984                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  2985 00005B26 C60300              <1> 	mov	byte [ebx], 0
  2986                              <1> ctty_3:
  2987                              <1> 	; 12/02/2022
  2988 00005B29 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2989 00005B2B 7401                <1> 	jz	short ctty_4
  2990                              <1> cret:
  2991                              <1> 	;pop	ax
  2992                              <1> 	; 05/02/2022
  2993 00005B2D 58                  <1> 	pop	eax
  2994                              <1> ctty_stc_retn:	; 12/02/2022
  2995                              <1> ctty_4:
  2996 00005B2E C3                  <1> 	retn
  2997                              <1> 
  2998                              <1> ;ctty_err: ; 13/01/2014
  2999                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3000                              <1> ;	jnz	error
  3001                              <1> ;	stc
  3002                              <1> ;	retn
  3003                              <1> 
  3004                              <1> 	; Original UNIX v1 'ctty' routine:
  3005                              <1> 	;	
  3006                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3007                              <1> 	;		;/ point r5 to the console tty buffer
  3008                              <1>         ;decb   (r5) / dec number of processes using console tty
  3009                              <1>         ;br     sret / return via sret
  3010                              <1> 
  3011                              <1> ;ccvt:	; < close tty >
  3012                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3013                              <1> 	;
  3014                              <1> 	; Retro UNIX 8086 v1 modification !
  3015                              <1> 	; 
  3016                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3017                              <1> 	;		(exactly different than this one)
  3018                              <1> 	;	was in 'u9.s' file.
  3019                              <1> 	;
  3020                              <1> 	; DL = 2 -> it is open for reading
  3021                              <1> 	; DL = 1 -> it is open for writing
  3022                              <1> 	;
  3023                              <1> 	; 17/09/2013
  3024                              <1> 	;sub 	al, 10
  3025                              <1> 	;cmp	al, 7
  3026                              <1> 	;jna	short cttyp
  3027                              <1> 	; 13/01/2014
  3028                              <1> 	;jmp	short cttyp
  3029                              <1> 
  3030                              <1> ;cppt: / close paper tape
  3031                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3032                              <1> ;1:
  3033                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3034                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3035                              <1> ;                          / and assign to free list
  3036                              <1> ;               br sret
  3037                              <1> ;        br     1b
  3038                              <1> 
  3039                              <1> ;ejec:	
  3040                              <1> ;	jmp	error
  3041                              <1> ;/ejec:
  3042                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3043                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3044                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3045                              <1> ;/       br     sret / return to caller via 'sret'
  2053                                  %include 'u8.s'        ; 11/06/2015
  2054                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2055                              <1> ; Last Modification: 12/02/2022
  2056                              <1> ; ----------------------------------------------------------------------------
  2057                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2058                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2059                              <1> ;
  2060                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2061                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2062                              <1> ; <Bell Laboratories (17/3/1972)>
  2063                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2064                              <1> ;
  2065                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2066                              <1> ;
  2067                              <1> ; ****************************************************************************
  2068                              <1> ; 24/10/2015
  2069                              <1> 
  2070                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2071                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2072                              <1> ;; Word 1, byte 0 = device id
  2073                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2074                              <1> ;;          bit 9 = write bit
  2075                              <1> ;;	    bit 10 = read bit	  
  2076                              <1> ;;	    bit 12 = waiting to write bit	
  2077                              <1> ;;	    bit 13 = waiting to read bit
  2078                              <1> ;;	    bit 15 = inhibit bit
  2079                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2080                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2081                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2082                              <1> ;;
  2083                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2084                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2085                              <1> ;;
  2086                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2087                              <1> ;; Word 1, Byte 0 = device id
  2088                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2089                              <1> ;;          bit 9 = write bit
  2090                              <1> ;;	    bit 10 = read bit	  
  2091                              <1> ;;	    bit 12 = waiting to write bit	
  2092                              <1> ;;	    bit 13 = waiting to read bit
  2093                              <1> ;;	    bit 15 = inhibit bit
  2094                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2095                              <1> ;;
  2096                              <1> ;; Original UNIX v1 ->
  2097                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2098                              <1> ;; Original UNIX v1 -> 
  2099                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2100                              <1> ;;
  2101                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2102                              <1> ;;
  2103                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2104                              <1> ;;          0 = fd0
  2105                              <1> ;;	    1 = fd1
  2106                              <1> ;;	    2 = hd0
  2107                              <1> ;;	    3 = hd1
  2108                              <1> ;;	    4 = hd2
  2109                              <1> ;;	    5 = hd3
  2110                              <1> 
  2111                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2112                              <1> 
  2113                              <1> 	; 04/02/2022
  2114                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2115                              <1> 	; 26/04/2013
  2116                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2117                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2118                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2119                              <1> 
  2120                              <1> 	; 04/02/2022
  2121                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2122                              <1> 	; 26/04/2013
  2123                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2124                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2125                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2126                              <1> 
  2127                              <1> bread: 
  2128                              <1> 	; 12/02/2022
  2129                              <1> 	; 04/02/2022
  2130                              <1> 	; 14/07/2015
  2131                              <1> 	; 10/07/2015
  2132                              <1> 	; 09/06/2015
  2133                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2134                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2135                              <1> 	;	
  2136                              <1> 	; / read a block from a block structured device
  2137                              <1> 	;
  2138                              <1> 	; INPUTS ->
  2139                              <1> 	;    [u.fofp] points to the block number
  2140                              <1> 	;    CX = maximum block number allowed on device
  2141                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2142                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2143                              <1> 	;    [u.count]	number of bytes to read in
  2144                              <1> 	; OUTPUTS ->
  2145                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2146                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2147                              <1> 	;
  2148                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2149                              <1> 	;
  2150                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2151                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2152                              <1> 	;	is increased by 1. For example: If user/program request 
  2153                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2154                              <1> 	;  	the next block number just as 512 byte reading is done.
  2155                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2156                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2157                              <1> 	;       enough to keep byte position/offset of the disk), this
  2158                              <1> 	;	defect will not be corrected, user/program must request
  2159                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2160                              <1> 	;       for achieving correct result. In future version(s), 
  2161                              <1> 	;	this defect will be corrected by using different 
  2162                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2163                              <1> 
  2164                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2165                              <1> 			       ; / (only works on tape)
  2166                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2167                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2168                              <1> ;1:
  2169                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2170                              <1> 			    ; / maximum block # allowed on device
  2171                              <1> 		; jnb short @f
  2172                              <1> 		; bhis	1f / yes, 1f (error)
  2173                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2174                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2175                              <1> 		; mov (sp)+,r1 / return block # to r1
  2176                              <1> 		; inc r1 / bump block # to next consecutive block
  2177                              <1> 		; dec (sp) / "2-1-cold" on stack
  2178                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2179                              <1> ;1:
  2180                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2181                              <1> 	;push	ecx ; **
  2182                              <1> 	;26/04/2013
  2183                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2184 00005B2F 2C03                <1> 	sub	al, 3
  2185                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2186 00005B31 A2[0E6F0000]        <1> 	mov	[u.brwdev], al
  2187                              <1> 	; 09/06/2015
  2188                              <1> 	;movzx	ebx, al
  2189                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2190                              <1> 	; 04/02/2022 (BugFix)
  2191 00005B36 C0E002              <1> 	shl	al, 2 ; * 4
  2192 00005B39 8B88[0E660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2193                              <1> bread_0:
  2194 00005B3F 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2195                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2196                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2197 00005B40 8B1D[BC6E0000]      <1> 	mov	ebx, [u.fofp]
  2198 00005B46 8B03                <1> 	mov	eax, [ebx]
  2199 00005B48 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2200                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2201                              <1> 			       ; / block #
  2202 00005B4B 39C8                <1> 	cmp	eax, ecx
  2203                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2204                              <1>        	                     ; / block number allowed
  2205                              <1> 	;jnb	error 	     ; 18/04/2013
  2206                              <1> 		; bhis error10 / yes, error
  2207                              <1> 	; 12/02/2022
  2208                              <1> 	;jb	short bread_1
  2209                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2210                              <1> 	;jmp	error
  2211 00005B4D 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2212                              <1> bread_1:
  2213                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2214                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2215                              <1> 	; eAX = Block number (zero based)
  2216                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2217                              <1> preread: ;; call preread
  2218 00005B4F BF[0E6F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2219 00005B54 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2220                              <1> 	;; jc 	error
  2221                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2222                              <1>         ; eAX = Block/Sector number (r1)
  2223                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2224                              <1> 	; 14/03/2013
  2225 00005B59 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2226                              <1>        		; br 1f / branch if block already in a I/O buffer
  2227 00005B5B 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2228                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2229 00005B60 E8DA010000          <1> 	call	poke
  2230                              <1>         	; jsr r0,poke / perform the read
  2231                              <1> 	;;jc	error ;2 0/07/2013
  2232                              <1> ; 1:
  2233                              <1>  		; clr *$ps / ps = 0
  2234                              <1>         	; rts r0
  2235                              <1> 	; 12/02/2022
  2236 00005B65 7305                <1> 	jnc	short bread_2
  2237 00005B67 E937010000          <1> 	jmp	dskrd_err
  2238                              <1> 
  2239                              <1> ;; return from preread
  2240                              <1> bread_2:
  2241 00005B6C 66810B0040          <1> 	or	word [ebx], 4000h 
  2242                              <1> 		; bis $40000,(r5) 
  2243                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2244                              <1> bread_3: ; 1:
  2245 00005B71 66F7030024          <1> 	test	word [ebx], 2400h
  2246                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2247 00005B76 7407                <1> 	jz	short bread_4
  2248                              <1> 		; beq 1f / no
  2249                              <1> 		; cmp cdev,$1 / disk or drum?
  2250                              <1> 		; ble 2f / yes
  2251                              <1> 		; tstb uquant / is the time quantum = 0?
  2252                              <1> 		; bne 2f / no, 2f
  2253                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2254                              <1> 		; jsr r0,sleep; 31. 
  2255                              <1> 			; / put process to sleep in channel 31 (tape)
  2256                              <1> 		; mov (sp)+,r5 / restore r5
  2257                              <1> 		; br 1b / go back
  2258                              <1> ; 2: / drum or disk
  2259                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2260 00005B78 E8B9F3FFFF          <1> 	call	idle
  2261                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2262 00005B7D EBF2                <1> 	jmp	short bread_3
  2263                              <1>        		; br 1b
  2264                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2265 00005B7F 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2266                              <1> 		; bic $40000,(r5) / clear bit 14
  2267                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2268 00005B84 83C308              <1> 	add	ebx, 8
  2269                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2270                              <1> 	; 09/06/2015
  2271 00005B87 66833D[0B6F0000]00  <1> 	cmp	word [u.pcount], 0
  2272 00005B8F 7705                <1> 	ja	short bread_5
  2273 00005B91 E875F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2274                              <1> bread_5:
  2275                              <1> 	; eBX = system (I/O) buffer address
  2276 00005B96 E870000000          <1> 	call	dioreg
  2277                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2278                              <1> 	; esi = start address of the transfer (in the buffer)
  2279                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2280                              <1> 	; ecx = transfer count (in bytes)
  2281                              <1> 	;
  2282                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2283                              <1> ;   / of users data
  2284 00005B9B F3A4                <1> 	rep	movsb
  2285                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2286                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2287                              <1>        		; bne 1b
  2288 00005B9D 59                  <1> 	pop	ecx ; **
  2289 00005B9E 833D[D06E0000]00    <1> 	cmp	dword [u.count], 0
  2290                              <1> 		; tst u.count / done
  2291 00005BA5 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2292                              <1>        		; beq 1f / yes, return
  2293                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2294                              <1>        		; br bread / read some more
  2295                              <1> ; 1:
  2296 00005BA7 58                  <1> 	pop	eax ; ****
  2297                              <1>        		; mov (sp)+,r0
  2298 00005BA8 C3                  <1>         retn		; 09/06/2015
  2299                              <1> 	;jmp	ret_ 
  2300                              <1> 		;jmp ret / jump to routine that called readi
  2301                              <1> 
  2302                              <1> 	; 08/02/2022
  2303                              <1> brw_oov_err:
  2304 00005BA9 C705[FB6E0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2304 00005BB1 0000                <1>
  2305 00005BB3 E92EDFFFFF          <1> 	jmp	error
  2306                              <1> 
  2307                              <1> 	; 12/02/2022
  2308                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2309                              <1> 	; 26/04/2013
  2310                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2311                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2312                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2313                              <1> 
  2314                              <1> 	; 12/02/2022				
  2315                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2316                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2317                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2318                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2319                              <1> 
  2320                              <1> bwrite: 
  2321                              <1> 	; 12/02/2022
  2322                              <1> 	; 04/02/2022
  2323                              <1> 	; 14/07/2015
  2324                              <1> 	; 10/07/2015
  2325                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2326                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2327                              <1> 	;	
  2328                              <1> 	;; / write on block structured device
  2329                              <1> 	;
  2330                              <1> 	; INPUTS ->
  2331                              <1> 	;    [u.fofp] points to the block number
  2332                              <1> 	;    CX = maximum block number allowed on device
  2333                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2334                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2335                              <1> 	;    [u.count]	number of bytes to user desires to write
  2336                              <1> 	; OUTPUTS ->
  2337                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2338                              <1> 	;
  2339                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2340                              <1> 	;
  2341                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2342                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2343                              <1> 	;	is increased by 1. For example: If user/program request 
  2344                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2345                              <1> 	;  	the next block number just as 512 byte writing is done.
  2346                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2347                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2348                              <1> 	;       enough to keep byte position/offset of the disk), this
  2349                              <1> 	;	defect will not be corrected, user/program must request
  2350                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2351                              <1> 	;       for achieving correct result. In future version(s), 
  2352                              <1> 	;	this defect will be corrected by using different 
  2353                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2354                              <1> 
  2355                              <1>        		; jsr r0,tstdeve / test the device for an error
  2356                              <1> 	;push	ecx ; **
  2357                              <1> 	;26/04/2013
  2358                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2359 00005BB8 2C03                <1> 	sub	al, 3
  2360                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2361 00005BBA A2[0E6F0000]        <1> 	mov	[u.brwdev], al
  2362                              <1> 	; 09/06/2015
  2363                              <1> 	;movzx	ebx, al
  2364                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2365                              <1> 	; 04/02/2022 (BugFix)
  2366 00005BBF C0E002              <1> 	shl	al, 2 ; * 4
  2367 00005BC2 8B88[0E660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2368                              <1> bwrite_0:
  2369 00005BC8 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2370                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2371                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2372 00005BC9 8B1D[BC6E0000]      <1> 	mov	ebx, [u.fofp]
  2373 00005BCF 8B03                <1> 	mov	eax, [ebx]       
  2374 00005BD1 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2375                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2376 00005BD4 39C8                <1> 	cmp	eax, ecx
  2377                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2378                              <1>        	                     ; / block number allowed
  2379                              <1> 	;jnb	error	     ; 18/04/2013
  2380                              <1> 		; bhis error10 / yes, error
  2381                              <1>      	; 12/02/2022
  2382                              <1> 	;jb	short bwrite_1
  2383                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2384                              <1> 	;jmp	error
  2385 00005BD6 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2386                              <1> bwrite_1:
  2387                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2388                              <1> 		; inc *u.fofp / no, increment block number
  2389                              <1> 	; 09/06/2015 - 10/07/2015
  2390 00005BD8 66833D[0B6F0000]00  <1> 	cmp	word [u.pcount], 0
  2391 00005BE0 7705                <1> 	ja	short bwrite_2
  2392 00005BE2 E820F9FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2393                              <1> bwrite_2:
  2394 00005BE7 BF[0E6F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2395 00005BEC E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2396                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2397                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2398 00005BF1 E815000000          <1>         call	dioreg
  2399                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2400                              <1> 	; esi =  destination address (in the buffer)
  2401                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2402                              <1> 	; ecx =  transfer count (in bytes)
  2403                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2404 00005BF6 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2405 00005BF8 F3A4                <1> 	rep	movsb
  2406                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2407                              <1>        		; dec r3 / area to the I/O buffer
  2408                              <1>        		; bne 1b
  2409 00005BFA E80D010000          <1> 	call	dskwr
  2410                              <1> 		; jsr r0,dskwr / write it out on the device
  2411 00005BFF 59                  <1> 	pop	ecx ; **
  2412 00005C00 833D[D06E0000]00    <1>         cmp     dword [u.count], 0
  2413                              <1> 		; tst u.count / done
  2414 00005C07 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2415                              <1> 		; beq 1f / yes, 1f
  2416                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2417                              <1>        		; br bwrite / go back and write next block
  2418                              <1> ; 1:
  2419 00005C09 58                  <1> 	pop	eax ; ****
  2420                              <1>        		; mov (sp)+,r0
  2421 00005C0A C3                  <1> 	retn		; 09/06/2015
  2422                              <1>         ;jmp	ret_ 
  2423                              <1> 		; jmp ret / return to routine that called writei
  2424                              <1> ;error10:
  2425                              <1> ;       jmp     error  ; / see 'error' routine
  2426                              <1> 
  2427                              <1> dioreg:
  2428                              <1> 	; 04/02/2022
  2429                              <1> 	; 14/07/2015
  2430                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2431                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2432                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2433                              <1> 	;	
  2434                              <1> 	; bookkeeping on block transfers of data
  2435                              <1> 	;
  2436                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2437                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2438                              <1> 	; 10/07/2015
  2439                              <1> 	; * returns byte offset from beginning of current sector buffer
  2440                              <1> 	; (beginning of data) in ESI
  2441                              <1> 	;
  2442 00005C0B 8B0D[D06E0000]      <1> 	mov	ecx, [u.count]
  2443                              <1> 		; mov u.count,r3 / move char count to r3
  2444                              <1>         ; 04/02/2022
  2445 00005C11 31D2                <1> 	xor	edx, edx
  2446 00005C13 B602                <1> 	mov	dh, 2
  2447                              <1> 	; edx = 512
  2448 00005C15 39D1                <1> 	cmp	ecx, edx ; 512
  2449                              <1> 	;cmp 	ecx, 512
  2450                              <1> 		; cmp r3,$512. / more than 512. char?
  2451 00005C17 7602                <1> 	jna	short dioreg_0
  2452                              <1> 		; blos 1f / no, branch
  2453 00005C19 89D1                <1> 	mov	ecx, edx ; 512
  2454                              <1> 	;mov	ecx, 512
  2455                              <1> 		; mov $512.,r3 / yes, just take 512.
  2456                              <1> dioreg_0:
  2457                              <1> 	; 09/06/2015
  2458 00005C1B 663B0D[0B6F0000]    <1> 	cmp	cx, [u.pcount]
  2459 00005C22 7607                <1> 	jna	short dioreg_1
  2460 00005C24 668B0D[0B6F0000]    <1> 	mov	cx, [u.pcount]
  2461                              <1> dioreg_1:
  2462                              <1> ; 1:
  2463 00005C2B 8B15[CC6E0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2464                              <1> 	        ; mov u.base,r2 / put users base in r2
  2465 00005C31 010D[D46E0000]      <1> 	add	[u.nread], ecx
  2466                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2467 00005C37 290D[D06E0000]      <1> 	sub	[u.count], ecx
  2468                              <1> 		; sub r3,u.count / update count
  2469 00005C3D 010D[CC6E0000]      <1> 	add	[u.base], ecx
  2470                              <1> 		; add r3,u.base / update base
  2471                              <1> 	; 10/07/2015
  2472                              <1> 	; Retro UNIX 386 v1 - modification !
  2473                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2474                              <1> 	; (It will point to next byte position instead of next block no.)
  2475 00005C43 8B35[BC6E0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2476 00005C49 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2477 00005C4B 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2478 00005C4D 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2479 00005C52 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2480 00005C54 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2481                              <1> 	; 09/06/2015 - 10/07/2015
  2482 00005C56 66290D[0B6F0000]    <1> 	sub	[u.pcount], cx
  2483 00005C5D 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2484 00005C63 8B3D[076F0000]      <1> 	mov	edi, [u.pbase]
  2485 00005C69 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2486 00005C6F 01D7                <1> 	add	edi, edx
  2487 00005C71 893D[076F0000]      <1> 	mov	[u.pbase], edi
  2488 00005C77 010D[076F0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2489 00005C7D C3                  <1> 	retn
  2490                              <1> 		; rts r0 / return
  2491                              <1> 
  2492                              <1> dskrd:
  2493                              <1> 	; 12/02/2022
  2494                              <1> 	; 18/08/2015
  2495                              <1> 	; 02/07/2015
  2496                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2497                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2498                              <1> 	;
  2499                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2500                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2501                              <1> 	; (number specified in r1) in the acquired buffer.
  2502                              <1> 	; If the device is busy at the time dskrd is called,	
  2503                              <1> 	; dskrd calls idle.
  2504                              <1> 	; 
  2505                              <1> 	; INPUTS ->
  2506                              <1> 	;    r1 - block number
  2507                              <1> 	;    cdev - current device number 
  2508                              <1> 	; OUTPUTS ->
  2509                              <1> 	;    r5 - points to first data word in I/O buffer
  2510                              <1> 	;
  2511                              <1> 	; ((AX = R1)) input/output
  2512                              <1> 	; ((BX = R5)) output 
  2513                              <1> 	;
  2514                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2515                              <1> 	;
  2516 00005C7E E851010000          <1> 	call 	bufaloc
  2517                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2518                              <1> 			       ; / get a free I/O buffer
  2519                              <1> 	;;jc	error ; 20/07/2013
  2520 00005C83 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2521                              <1>        		; br 1f / branch if block already in a I/O buffer
  2522                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2523 00005C85 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2524                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2525                              <1> 		               ; / I/O queue entry for buffer
  2526 00005C8A E8B0000000          <1> 	call	poke
  2527                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2528                              <1> 			    ; /	bit 10=1 says read
  2529                              <1> 	; 09/06/2015
  2530                              <1> 	;jnc	short dskrd_1
  2531                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2532                              <1> 	;jmp	error
  2533                              <1> 	; 08/02/2022
  2534 00005C8F 7212                <1> 	jc	short dskrd_3
  2535                              <1> dskrd_1: ; 1:
  2536                              <1>        		;clr *$ps
  2537 00005C91 66F7030024          <1>        	test	word [ebx], 2400h
  2538                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2539                              <1> 				; / jump to idle
  2540 00005C96 7407                <1>        	jz	short dskrd_2
  2541                              <1> 		; beq 1f
  2542                              <1>         ;;mov   ecx, [s.wait_]
  2543 00005C98 E899F2FFFF          <1>        	call	idle
  2544                              <1> 		; jsr r0,idle; s.wait+2
  2545 00005C9D EBF2                <1> 	jmp 	short dskrd_1
  2546                              <1>        		; br 1b
  2547                              <1> dskrd_2: ; 1:
  2548 00005C9F 83C308              <1>         add	ebx, 8
  2549                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2550                              <1> 			  ; / just read in
  2551 00005CA2 C3                  <1>        	retn
  2552                              <1> 		; rts r0
  2553                              <1> dskrd_err: 
  2554                              <1> 	; 08/02/2022
  2555                              <1> 	; (jump from 'bread' error)
  2556                              <1> dskrd_3:	
  2557                              <1> 	; 08/02/2022
  2558 00005CA3 803D[0E6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2559 00005CAA 7509                <1> 	jne	short dskrd_4 ; no
  2560                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2561 00005CAC C605[0E6F0000]00    <1> 	mov	byte [u.brwdev], 0
  2562 00005CB3 EB0A                <1> 	jmp	short dskrd_5
  2563                              <1> dskrd_4:
  2564 00005CB5 C705[FB6E0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2564 00005CBD 0000                <1>
  2565                              <1> dskrd_5:
  2566 00005CBF E922DEFFFF          <1> 	jmp	error
  2567                              <1> 
  2568                              <1> bwslot:
  2569                              <1> 	; 04/02/2022
  2570                              <1> 	; 10/07/2015
  2571                              <1> 	;	If the block/sector is not placed in a buffer
  2572                              <1> 	;	before 'wslot', it must be read before
  2573                              <1> 	;	it is written! (Otherwise transfer counts less
  2574                              <1> 	;	than 512 bytes will be able to destroy existing 
  2575                              <1> 	;	data on disk.)
  2576                              <1> 	;
  2577                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2578                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2579                              <1> 	; Retro UNIX 8086 v1 modification !
  2580                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2581                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2582                              <1> 	;	-> eAX = block number
  2583                              <1> 	;
  2584 00005CC4 E818010000          <1> 	call	bufaloc_0
  2585 00005CC9 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2586                              <1> 	; 04/02/2022
  2587                              <1> 	; ebx = buffer header address
  2588                              <1> bwslot_0:
  2589                              <1> 	; 10/07/2015
  2590 00005CCB 8B35[BC6E0000]      <1> 	mov	esi, [u.fofp]
  2591 00005CD1 8B06                <1> 	mov	eax, [esi]
  2592 00005CD3 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2593 00005CD8 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2594                              <1> 		       ; recent disk data must be placed in the buffer
  2595 00005CDA 813D[D06E0000]0002- <1> 	cmp	dword [u.count], 512
  2595 00005CE2 0000                <1>
  2596 00005CE4 730F                <1> 	jnb	short wslot_0	
  2597                              <1> bwslot_1:
  2598 00005CE6 E89AFFFFFF          <1> 	call	dskrd_0
  2599                              <1> 	; 04/02/2022
  2600                              <1> 	; ebx = buffer data address = buffer header address + 8
  2601 00005CEB 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2602 00005CEE EB05                <1> 	jmp 	short wslot_0
  2603                              <1> 
  2604                              <1> wslot:
  2605                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2606                              <1> 	; 		(32 bit modifications)
  2607                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2608                              <1> 	;
  2609                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2610                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2611                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2612                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2613                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2614                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2615                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2616                              <1> 	;
  2617                              <1> 	; INPUTS ->
  2618                              <1>  	;    r1 - block number
  2619                              <1> 	;    cdev - current (block/disk) device number
  2620                              <1>  	;
  2621                              <1> 	; OUTPUTS ->
  2622                              <1> 	;    bufp - bits 9 and 15 are set, 
  2623                              <1> 	;           the remainder of the word left unchanged
  2624                              <1> 	;    r5 - points to first data word in I/O buffer
  2625                              <1> 	;
  2626                              <1> 	; ((AX = R1)) input/output
  2627                              <1> 	; ((BX = R5)) output 
  2628                              <1> 	;
  2629                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2630                              <1> 
  2631 00005CF0 E8DF000000          <1> 	call	bufaloc
  2632                              <1> 	; 10/07/2015
  2633                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2634                              <1>         	; br 1f / word in buffer in r5
  2635                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2636                              <1>         ; eAX = Block/Sector number (r1)
  2637                              <1> wslot_0: ;1:
  2638 00005CF5 66F7030024          <1>      	test	word [ebx], 2400h
  2639                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2640                              <1> 				; / of I/O queue entry
  2641 00005CFA 7407                <1> 	jz	short wslot_1
  2642                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2643                              <1> 		        ; / or not waiting to read)
  2644                              <1> 
  2645                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2646 00005CFC E835F2FFFF          <1> 	call	idle
  2647                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2648                              <1>        	                     ; / idle
  2649 00005D01 EBF2                <1> 	jmp	short wslot_0
  2650                              <1> 		; br 1b / till finished
  2651                              <1> wslot_1: ;1:
  2652 00005D03 66810B0082          <1> 	or      word [ebx], 8200h
  2653                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2654                              <1>                             	 ; / (write, inhibit bits)
  2655                              <1>        		; clr *$ps / clear processor status
  2656 00005D08 83C308              <1> 	add	ebx, 8 ; 11/06/2015
  2657                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2658                              <1> 			  ; / for this block
  2659                              <1> dskwr_1:	; 08/02/2022
  2660 00005D0B C3                  <1> 	retn
  2661                              <1> 		; rts r0
  2662                              <1> dskwr:
  2663                              <1> 	; 12/02/2022
  2664                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2665                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2666                              <1> 	;
  2667                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2668                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2669                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2670                              <1> 	; previously has supplied all the information required in the
  2671                              <1> 	; I/O queue entry.
  2672                              <1> 	;
  2673                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2674                              <1> 	;
  2675                              <1> 	;
  2676 00005D0C 8B1D[6C6E0000]      <1> 	mov	ebx, [bufp]
  2677 00005D12 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2678                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2679                              <1>                                   ; / bottom of queue
  2680 00005D17 E823000000          <1> 	call	poke
  2681                              <1> 	; 09/06/2015
  2682 00005D1C 73ED                <1> 	jnc	short dskwr_1
  2683                              <1> 	; 12/02/2022
  2684 00005D1E 803D[0E6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2685 00005D25 7509                <1> 	jne	short dskwr_0 ; no
  2686                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2687 00005D27 C605[0E6F0000]00    <1> 	mov	byte [u.brwdev], 0
  2688 00005D2E EB0A                <1> 	jmp	short dskwr_2
  2689                              <1> dskwr_0:
  2690 00005D30 C705[FB6E0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2690 00005D38 0000                <1>
  2691                              <1> dskwr_2:
  2692 00005D3A E9A7DDFFFF          <1> 	jmp	error
  2693                              <1> ;dskwr_1:
  2694                              <1> ;	retn
  2695                              <1> 
  2696                              <1> ;ppoke:
  2697                              <1>        		; mov $340,*$ps
  2698                              <1>        		; jsr r0,poke
  2699                              <1>        		; clr *$ps
  2700                              <1> 		; rts r0
  2701                              <1> poke:
  2702                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2703                              <1> 	; 24/10/2015
  2704                              <1> 	; 20/08/2015
  2705                              <1> 	; 18/08/2015
  2706                              <1> 	; 02/07/2015
  2707                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2708                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2709                              <1> 	;
  2710                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2711                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2712                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2713                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2714                              <1> 	;
  2715                              <1> 	; Basic I/O functions for all block structured devices
  2716                              <1> 	;
  2717                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2718                              <1> 	;
  2719                              <1> 	; 20/07/2013 modifications
  2720                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2721                              <1> 	; INPUTS -> 
  2722                              <1> 	;        (EBX = buffer header address)
  2723                              <1> 	; OUTPUTS ->
  2724                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2725                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2726                              <1> 	;		(drive not ready or r/w error!)
  2727                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2728                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2729                              <1> 	;        (also it indicates invalid buffer data)
  2730                              <1> 	;
  2731 00005D3F 53                  <1> 	push	ebx
  2732                              <1>        		; mov r1,-(sp)
  2733                              <1>        		; mov r2,-(sp)
  2734                              <1>        		; mov r3,-(sp)
  2735 00005D40 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2736                              <1> 	;
  2737                              <1> 	; 09/06/2015
  2738                              <1> 	; (permit read/write after a disk R/W error)
  2739 00005D41 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2740 00005D43 B001                <1> 	mov	al, 1
  2741 00005D45 D2E0                <1> 	shl	al, cl
  2742 00005D47 8405[946E0000]      <1> 	test 	al, [active] ; busy ? (error)
  2743 00005D4D 7408                <1> 	jz	short poke_0
  2744 00005D4F F6D0                <1> 	not	al
  2745 00005D51 2005[946E0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2746                              <1> poke_0:
  2747 00005D57 BE[8C6E0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2748                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2749                              <1> 					 ; / I/O queue pointer
  2750                              <1> poke_1: ; 1:
  2751 00005D5C 83EE04              <1>         sub	esi, 4
  2752 00005D5F 8B1E                <1> 	mov	ebx, [esi]
  2753                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2754 00005D61 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2755 00005D64 F6C406              <1>        	test	ah, 06h
  2756                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2757                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2758                              <1> 			       ; / queue entry
  2759 00005D67 745C                <1>         jz      short poke_5
  2760                              <1> 		; beq 2f / branch to 2f if both are clear
  2761                              <1> 	; 31/07/2013
  2762                              <1> 	;test	ah, 0B0h ; (*)
  2763                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2764                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2765                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2766                              <1> 		; bne 2f / branch if any are set
  2767                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2768                              <1>     		; movb (r1),r3 / get device id
  2769 00005D69 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2770                              <1> 	;mov	edi, ecx ; 26/04/2013
  2771 00005D6C 31C0                <1> 	xor 	eax, eax ; 0
  2772                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2773                              <1> 		; tstb deverr(r3) / test for errors on this device
  2774                              <1>        	;jna	short poke_2 
  2775                              <1> 		; beq 3f / branch if no errors
  2776                              <1> 	; 02/07/2015
  2777                              <1> 	;dec	eax
  2778                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2779                              <1>        		; mov $-1,2(r1) / destroy associativity
  2780                              <1> 	;shr	eax, 24
  2781                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2782                              <1> 		; clrb 1(r1) / do not do I/O
  2783                              <1> 	;jmp     short poke_5
  2784                              <1>         ;       ; br 2f
  2785                              <1>                 ; rts r0
  2786                              <1> poke_2: ; 3:
  2787                              <1> 	; 02/07/2015
  2788 00005D6E FEC1                <1> 	inc	cl ; 0FFh -> 0
  2789 00005D70 7453                <1> 	jz	short poke_5
  2790 00005D72 FEC0                <1> 	inc	al ; mov ax, 1
  2791 00005D74 FEC9                <1> 	dec	cl
  2792 00005D76 7402                <1> 	jz	short poke_3
  2793                              <1> 	; 26/04/2013 Modification
  2794                              <1> 	;inc	al ; mov ax, 1
  2795                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2796                              <1> 	;jz	short poke_3 ; cl = 0
  2797 00005D78 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2798                              <1> poke_3:
  2799                              <1> 	;test	[active], ax
  2800 00005D7A 8405[946E0000]      <1> 	test	[active], al
  2801                              <1> 		; bit $2,active / test disk busy bit
  2802 00005D80 7543                <1> 	jnz     short poke_5
  2803                              <1> 		; bne 2f / branch if bit is set
  2804                              <1> 	;or	[active], ax
  2805 00005D82 0805[946E0000]      <1> 	or	[active], al
  2806                              <1> 		; bis $2,active / set disk busy bit
  2807                              <1> 	;push	ax
  2808                              <1> 	; 04/02/2022
  2809 00005D88 50                  <1> 	push	eax
  2810 00005D89 E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2811                              <1> 	;mov    [edi+drv.error], ah
  2812                              <1> 	; 04/02/2022
  2813 00005D8E 58                  <1> 	pop	eax
  2814                              <1> 	;pop	ax
  2815 00005D8F 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2816                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2817                              <1> 	;jna	short poke_4
  2818                              <1> 		; tstb deverr(r3) / test for errors on this device
  2819                              <1>        		; beq 3f / branch if no errors
  2820                              <1> 	; 02/07/2015 (32 bit modification)
  2821                              <1> 	; 20/07/2013
  2822 00005D91 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2823                              <1>        		; mov $-1,2(r1) / destroy associativity
  2824 00005D98 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2825                              <1> 		; clrb 1(r1) / do not do I/O
  2826 00005D9D EB26                <1> 	jmp     short poke_5
  2827                              <1> poke_4:	; 20/07/2013
  2828                              <1> 	; 17/07/2013
  2829 00005D9F F6D0                <1> 	not 	al 
  2830 00005DA1 2005[946E0000]      <1> 	and	[active], al ; reset, not busy
  2831                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2832                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2833 00005DA7 668B03              <1> 	mov	ax, [ebx]
  2834                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2835 00005DAA 66250006            <1>         and	ax, 600h
  2836                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2837 00005DAE 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2838                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2839 00005DB3 C0E403              <1> 	shl	ah, 3
  2840                              <1>        		; rol r3
  2841                              <1>                 ; rol r3
  2842                              <1>                 ; rol r3	
  2843 00005DB6 660903              <1> 	or	[ebx], ax
  2844                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2845                              <1> 			   ; bits 12 and 13
  2846 00005DB9 E878F1FFFF          <1> 	call	idle ; 18/01/2014
  2847                              <1> 	;; sti
  2848                              <1> 	;hlt 	; wait for a hardware interrupt
  2849                              <1> 	;; cli
  2850                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2851                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2852                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2853                              <1> 	; method, this procedure will wait for a time according to
  2854                              <1> 	; multi tasking and time sharing concept.
  2855                              <1> 	;
  2856                              <1> 	; 24/10/2015
  2857                              <1> 	;not	ax 
  2858 00005DBE 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2859 00005DC2 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2860                              <1> poke_5: ;2:
  2861 00005DC5 81FE[6C6E0000]      <1>         cmp     esi, bufp
  2862                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2863                              <1>                             ; / has been scanned
  2864 00005DCB 778F                <1> 	ja      short poke_1
  2865                              <1>                ; bhi 1b
  2866                              <1> 	; 24/03/2013
  2867                              <1>        		; mov (sp)+,r3
  2868                              <1>        		; mov (sp)+,r2
  2869                              <1>        		; mov (sp)+,r1
  2870 00005DCD 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2871 00005DCE 5B                  <1> 	pop 	ebx
  2872                              <1> 	; 02/07/2015 (32 bit modification)
  2873                              <1> 	; 20/07/2013
  2874                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2875 00005DCF 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2876                              <1> 	;	
  2877                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2878                              <1> 	; or written succesfully; even if an error occurs while
  2879                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2880                              <1> 	;
  2881                              <1> 	; 09/06/2015
  2882 00005DD2 F5                  <1> 	cmc
  2883 00005DD3 C3                  <1> 	retn
  2884                              <1>                 ; rts r0
  2885                              <1> 
  2886                              <1> bufaloc:
  2887                              <1> 	; 04/02/2022
  2888                              <1> 	; 20/08/2015
  2889                              <1> 	; 19/08/2015
  2890                              <1> 	; 02/07/2015
  2891                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2892                              <1> 	;	     (32 bit modifications)	
  2893                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2894                              <1> 	;
  2895                              <1> 	; bufaloc - Block device I/O buffer allocation
  2896                              <1> 	; 
  2897                              <1> 	; INPUTS ->
  2898                              <1> 	;    r1 - block number
  2899                              <1> 	;    cdev - current (block/disk) device number
  2900                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2901                              <1> 	; OUTPUTS ->
  2902                              <1> 	;    r5 - pointer to buffer allocated
  2903                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2904                              <1> 	;
  2905                              <1> 	; ((AX = R1)) input/output
  2906                              <1> 	; ((BX = R5)) output
  2907                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2908                              <1> 	;    zf=1 -> block already in a I/O buffer
  2909                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2910                              <1> 	;    ((DL = Device ID))
  2911                              <1> 	;    (((DH = 0 or 1)))
  2912                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2913                              <1> 	;    ((CX and DH will not be used after return)))
  2914                              <1> 
  2915                              <1> 	;;push 	esi ; ***
  2916                              <1> 		; mov r2,-(sp) / save r2 on stack
  2917                              <1>        		; mov $340,*$ps / set processor priority to 7
  2918                              <1> 		; 20/07/2013
  2919                              <1> 	; 26/04/2013
  2920                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2921                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  2922                              <1> 	;add	edi, ebx
  2923                              <1> 	; 09/01/2022
  2924 00005DD4 0FB63D[906E0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2925 00005DDB 81C7[926E0000]      <1> 	add	edi, rdev
  2926                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2927                              <1> 			;; eDI points to device id.
  2928 00005DE1 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2929                              <1> 	; 11/06/2015
  2930 00005DE4 80BB[2A660000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2931 00005DEB 720F                <1> 	jb	short bufaloc_9
  2932 00005DED C705[FB6E0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2932 00005DF5 0000                <1>
  2933 00005DF7 E9EADCFFFF          <1> 	jmp	error
  2934                              <1> bufaloc_9:
  2935 00005DFC 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2936                              <1> bufaloc_10: ; 02/07/2015
  2937 00005DFE 31ED                <1> 	xor 	ebp, ebp ; 0
  2938 00005E00 55                  <1> 	push	ebp ; 0
  2939 00005E01 89E5                <1>         mov     ebp, esp	
  2940                              <1> 	;
  2941                              <1> bufaloc_1: ;1:
  2942                              <1> 		; clr -(sp) / vacant buffer
  2943 00005E03 BE[6C6E0000]        <1>         mov 	esi, bufp
  2944                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2945                              <1> 			     ; / entrys in buffer area
  2946                              <1> bufaloc_2: ;2:
  2947 00005E08 8B1E                <1> 	mov	ebx, [esi]
  2948                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2949                              <1> 			    ; queue entry into r5
  2950 00005E0A 66F70300F6          <1> 	test	word [ebx], 0F600h
  2951                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2952 00005E0F 7503                <1>         jnz	short bufaloc_3
  2953                              <1> 		; bne 3f / branch when 
  2954                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2955                              <1>                        ; / (i.e., buffer busy)
  2956 00005E11 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2957                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2958                              <1> 			; / found points to word 2 of I/O queue entry)
  2959                              <1> bufaloc_3: ;3:
  2960                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2961                              <1> 	;
  2962 00005E14 3813                <1> 	cmp	[ebx], dl	
  2963                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2964                              <1> 			       ; / as current device
  2965 00005E16 7508                <1> 	jne	short bufaloc_4
  2966                              <1>        		; bne 3f
  2967 00005E18 394304              <1> 	cmp	[ebx+4], eax
  2968                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2969                              <1> 			     ; / same as current block number
  2970 00005E1B 7503                <1>        	jne	short bufaloc_4
  2971                              <1> 		; bne 3f
  2972                              <1> 	;add	esp, 4
  2973 00005E1D 59                  <1> 	pop	ecx
  2974                              <1>        		; tst (sp)+ / bump stack pointer
  2975 00005E1E EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2976                              <1> 				; jump to bufaloc_6 in original Unix v1
  2977                              <1>        		; br 1f / use this buffer
  2978                              <1> bufaloc_4: ;3:
  2979 00005E20 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2980                              <1> 	;
  2981 00005E23 81FE[846E0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2982                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2983 00005E29 72DD                <1> 	jb	short bufaloc_2
  2984                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2985                              <1>                        ; / buffers not checked)
  2986 00005E2B 5E                  <1>         pop	esi
  2987                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2988                              <1> 			     ; / to last free block
  2989 00005E2C 09F6                <1>        	or	esi, esi 
  2990 00005E2E 7507                <1> 	jnz	short bufaloc_5
  2991                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2992                              <1> 	        ; / if a free buffer is found branch to 2f
  2993                              <1>         ;; mov  ecx, [s.wait_]
  2994 00005E30 E801F1FFFF          <1> 	call	idle
  2995                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2996 00005E35 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2997                              <1>        		; br 1b
  2998                              <1> bufaloc_5: ;2:
  2999                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3000 00005E37 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3001                              <1> bufaloc_6: ;1:
  3002 00005E39 8B1E                <1>         mov    	ebx, [esi] 
  3003                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3004                              <1> 			     ; / entry in r5
  3005                              <1> 	;; 26/04/2013
  3006                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3007 00005E3B 8813                <1> 	mov 	[ebx], dl
  3008                              <1> 		; movb cdev,(r5) / put current device number 
  3009                              <1> 				 ; / in I/O queue entry
  3010 00005E3D 894304              <1> 	mov 	[ebx+4], eax
  3011                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3012                              <1> 			     ; / of I/O queue entry
  3013                              <1> bufaloc_7: ;1:
  3014 00005E40 81FE[6C6E0000]      <1>         cmp	esi, bufp
  3015                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3016                              <1> 			     ; / and put latest assigned
  3017 00005E46 760A                <1> 	jna	short bufaloc_8	
  3018                              <1>        		; blos 1f / buffer on the top 
  3019                              <1> 			; / (this makes if the lowest priority)
  3020 00005E48 83EE04              <1> 	sub	esi, 4
  3021 00005E4B 8B0E                <1> 	mov	ecx, [esi]
  3022 00005E4D 894E04              <1> 	mov	[esi+4], ecx
  3023                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3024 00005E50 EBEE                <1> 	jmp 	short bufaloc_7        
  3025                              <1> 		; br 1b
  3026                              <1> bufaloc_8: ;1:
  3027 00005E52 891E                <1>         mov	[esi], ebx
  3028                              <1> 		; mov r5,(r2)
  3029                              <1> 	;;pop	esi ; ***
  3030                              <1>        		; mov (sp)+,r2 / restore r2
  3031 00005E54 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3032                              <1> 		; Retro UNIX 8086 v1 modification
  3033                              <1> 		; zf=1 --> block already is in an I/O buffer
  3034                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3035 00005E56 C3                  <1> 	retn
  3036                              <1> 		; rts r0
  3037                              <1> 
  3038                              <1> diskio:
  3039                              <1> 	; 12/02/2022
  3040                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  3041                              <1> 	; 10/07/2015
  3042                              <1> 	; 02/07/2015
  3043                              <1> 	; 16/06/2015
  3044                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3045                              <1> 	;	     (80386 protected mode modifications)	
  3046                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3047                              <1> 	;
  3048                              <1> 	; Retro UNIX 8086 v1 feature only !
  3049                              <1> 	;
  3050                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3051                              <1> 	; 04/07/2009 - 20/07/2011
  3052                              <1> 	;
  3053                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3054                              <1> 	;
  3055                              <1>         ; INPUTS ->
  3056                              <1> 	; 	   eBX = System I/O Buffer header address
  3057                              <1> 	;
  3058                              <1>         ; OUTPUTS -> cf=0 --> done 
  3059                              <1> 	; 	     cf=1 --> error code in AH
  3060                              <1> 	;
  3061                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3062                              <1> 	
  3063                              <1> ;rw_disk_sector:
  3064                              <1> 	; 12/02/2022
  3065                              <1> 	; 10/07/2015
  3066                              <1> 	; 02/07/2015
  3067                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3068                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3069                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3070                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3071                              <1> 	;
  3072                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3073 00005E57 B602                <1> 	mov	dh, 2
  3074 00005E59 668B03              <1> 	mov	ax, [ebx] 
  3075                              <1> 	;
  3076 00005E5C 56                  <1> 	push	esi ; ****
  3077 00005E5D 53                  <1> 	push	ebx ; ***
  3078                              <1> 	;
  3079 00005E5E 0FB6C8              <1> 	movzx	ecx, al
  3080 00005E61 89CE                <1> 	mov	esi, ecx
  3081                              <1> 	;
  3082 00005E63 38F1                <1> 	cmp	cl, dh ; 2
  3083 00005E65 7202                <1> 	jb	short rwdsk0
  3084 00005E67 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3085                              <1> rwdsk0:
  3086 00005E69 A2[DB650000]        <1> 	mov	[drv], al
  3087 00005E6E 81C6[2A660000]      <1> 	add	esi, drv.status
  3088                              <1> 	; 11/06/2015
  3089 00005E74 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3090 00005E77 7204                <1> 	jb      short rwdsk1
  3091                              <1> 	; 'drive not ready' error
  3092                              <1> 	; 12/02/2022
  3093                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3094                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3095                              <1> 	;;jmp	error
  3096                              <1> 	;stc	; cf = 1
  3097                              <1> 	;retn
  3098                              <1> 	; 12/02/2022
  3099 00005E79 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3100 00005E7B EB20                <1> 	jmp	short rwdsk_err1
  3101                              <1> rwdsk1:
  3102 00005E7D F6C402              <1> 	test	ah, 2
  3103                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3104                              <1> 			 ; write bit
  3105 00005E80 7402                <1> 	jz	short rwdsk2
  3106                              <1> 	;test	ah, 4
  3107                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3108                              <1> 	;		 ; read bit
  3109                              <1> 	;jz	short diskio_ret
  3110 00005E82 FEC6                <1> 	inc	dh ; 03h = write
  3111                              <1> rwdsk2:
  3112 00005E84 88C2                <1> 	mov	dl, al
  3113 00005E86 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3114 00005E89 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3115 00005E8B C0E102              <1> 	shl	cl, 2
  3116 00005E8E 81C1[0E660000]      <1> 	add	ecx, drv.size ; disk size
  3117 00005E94 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3118 00005E96 7214                <1> 	jb      short rwdsk3
  3119                              <1>  	; 'out of volume' error
  3120                              <1> 	; 12/02/2022
  3121                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3122                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3123                              <1> 	;;jmp	error
  3124                              <1> 	;stc	; cf = 1
  3125                              <1> 	;retn
  3126                              <1> 	; 12/02/2022
  3127 00005E98 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3128                              <1> rwdsk_err1:
  3129 00005E9D C605[0E6F0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3130 00005EA4 890D[FB6E0000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3131 00005EAA EB30                <1> 	jmp	short rwdsk_err2
  3132                              <1> rwdsk3:
  3133                              <1> 	; 11/06/2015
  3134 00005EAC 83C304              <1> 	add	ebx, 4 ; buffer address
  3135 00005EAF C605[2A6F0000]04    <1> 	mov	byte [retry_count], 4
  3136 00005EB6 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3137 00005EB9 7432                <1>         jz      short rwdsk_chs
  3138                              <1> rwdsk_lba:
  3139                              <1> 	; LBA read/write (with private LBA function) 
  3140                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3141 00005EBB 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3142 00005EBE 89C1                <1> 	mov	ecx, eax ; sector number
  3143                              <1> 	; ebx = buffer (data) address
  3144                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3145                              <1> rwdsk_lba_retry:
  3146                              <1> 	;mov	dl, [drv]
  3147                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3148 00005EC0 B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3149 00005EC2 00F4                <1> 	add	ah, dh		
  3150 00005EC4 B001                <1> 	mov	al, 1
  3151                              <1> 	;int	13h
  3152 00005EC6 E8EFC6FFFF          <1> 	call	int13h
  3153 00005ECB 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3154 00005ECD 730E                <1> 	jnc	short rwdsk_lba_ok
  3155 00005ECF 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3156 00005ED2 7408                <1>         je      short rwdsk_lba_fails
  3157 00005ED4 FE0D[2A6F0000]      <1> 	dec	byte [retry_count]
  3158 00005EDA 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3159                              <1> rwdsk_err2:	; 12/02/2022
  3160                              <1> rwdsk_lba_fails:
  3161 00005EDC F9                  <1> 	stc
  3162                              <1> rwdsk_lba_ok:
  3163 00005EDD 5B                  <1> 	pop	ebx ; ***
  3164 00005EDE 5E                  <1> 	pop	esi ; ****
  3165 00005EDF C3                  <1> 	retn
  3166                              <1> rwdsk_lba_reset:
  3167 00005EE0 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3168                              <1> 	;int	13h
  3169 00005EE2 E8D3C6FFFF          <1>         call	int13h
  3170 00005EE7 73D7                <1> 	jnc     short rwdsk_lba_retry
  3171 00005EE9 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3172 00005EEB EBF0                <1> 	jmp	short rwdsk_lba_ok
  3173                              <1> 	;
  3174                              <1> 	; CHS read (convert LBA address to CHS values)	
  3175                              <1> rwdsk_chs:
  3176                              <1> 	; 10/07/2015
  3177 00005EED 81EE[2A660000]      <1> 	sub	esi, drv.status
  3178 00005EF3 89F1                <1> 	mov	ecx, esi
  3179 00005EF5 81C6[31660000]      <1> 	add 	esi, drv.error
  3180                              <1> 	; 02/07/2015
  3181                              <1> 	; 16/06/2015
  3182                              <1>  	; 11/06/2015 
  3183 00005EFB 53                  <1> 	push	ebx ; ** ; buffer
  3184 00005EFC D1E1                <1> 	shl	ecx, 1
  3185 00005EFE 51                  <1> 	push	ecx ; * 
  3186                              <1> 	;
  3187 00005EFF 89CB                <1> 	mov	ebx, ecx
  3188 00005F01 8835[296F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3189 00005F07 31D2                <1> 	xor	edx, edx ; 0
  3190                              <1> 	; 04/02/2022
  3191                              <1> 	;sub	ecx, ecx 
  3192 00005F09 81C3[00660000]      <1>         add     ebx, drv.spt
  3193 00005F0F 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3194                              <1> 		; EDX:EAX = LBA
  3195 00005F12 F7F1                <1> 	div	ecx
  3196 00005F14 88D1                <1> 	mov	cl, dl	; sector number - 1
  3197 00005F16 FEC1                <1> 	inc	cl	; sector number (1 based)
  3198 00005F18 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3199                              <1> 	;push	cx
  3200                              <1>         ; 04/02/2022
  3201 00005F19 51                  <1> 	push	ecx
  3202 00005F1A 81C3[F2650000]      <1>         add     ebx, drv.heads
  3203 00005F20 668B0B              <1> 	mov	cx, [ebx] ; heads
  3204 00005F23 31D2                <1> 	xor	edx, edx
  3205                              <1> 		; EAX = cylinders * heads + head
  3206 00005F25 F7F1                <1> 	div	ecx
  3207                              <1> 	;pop	cx     ; sector number
  3208                              <1> 	; 04/02/2022
  3209 00005F27 59                  <1> 	pop	ecx
  3210 00005F28 88D6                <1> 	mov	dh, dl ; head number
  3211 00005F2A 8A15[DB650000]      <1> 	mov	dl, [drv]
  3212 00005F30 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3213 00005F32 C0E406              <1> 	shl	ah, 6
  3214 00005F35 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3215                              <1> 		       ; sector (bits 0-7)
  3216 00005F37 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3217                              <1> 		; CL = sector (bits 0-5)
  3218                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3219                              <1> 		; CH = cylinder (bits 0-7)
  3220                              <1> 		; DH = head
  3221                              <1> 		; DL = drive
  3222                              <1> 	;
  3223 00005F38 C605[2A6F0000]04    <1> 	mov	byte [retry_count], 4
  3224                              <1> rwdsk_retry:	
  3225 00005F3F 8A25[296F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3226 00005F45 B001                <1> 	mov	al, 1 ; sector count	
  3227                              <1> 	;int	13h
  3228 00005F47 E86EC6FFFF          <1> 	call	int13h
  3229 00005F4C 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3230 00005F4E 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3231 00005F50 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3232 00005F53 7408                <1> 	je	short rwdsk_fails
  3233 00005F55 FE0D[2A6F0000]      <1> 	dec	byte [retry_count]
  3234 00005F5B 7504                <1> 	jnz	short rwdsk_reset
  3235                              <1> rwdsk_fails:
  3236 00005F5D F9                  <1> 	stc
  3237                              <1> rwdsk_ok:
  3238 00005F5E 5B                  <1> 	pop	ebx ; ***
  3239 00005F5F 5E                  <1> 	pop	esi ; ****
  3240 00005F60 C3                  <1> 	retn
  3241                              <1> rwdsk_reset:
  3242                              <1> 	; 02/02/2015
  3243 00005F61 28E4                <1> 	sub	ah, ah
  3244 00005F63 80FA80              <1> 	cmp	dl, 80h
  3245 00005F66 7202                <1> 	jb	short rwdsk_fd_reset
  3246 00005F68 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3247                              <1> rwdsk_fd_reset:
  3248                              <1> 	;int	13h
  3249 00005F6A E84BC6FFFF          <1>         call	int13h
  3250 00005F6F 73CE                <1> 	jnc	short rwdsk_retry
  3251 00005F71 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3252 00005F73 EBE9                <1> 	jmp 	short rwdsk_ok
  3253                              <1> 
  3254                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3255                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3256                              <1> ;
  3257                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3258                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3259                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3260                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3261                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3262                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3263                              <1> ; as in original unix v1.
  3264                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3265                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3266                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3267                              <1> ;
  3268                              <1> ; Erdogan tan (10/07/2015) 
  3269                              <1> 
  3270                              <1> ;drum: / interrupt handler
  3271                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3272                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3273                              <1> ;                                      / error
  3274                              <1> ;               br 3f / no, error
  3275                              <1> ;       br      2f / error
  3276                              <1> ;
  3277                              <1> ;disk:
  3278                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3279                              <1> ;       jmp     *$0f
  3280                              <1> ;0:
  3281                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3282                              <1> ;      	        br 3f / no, errors
  3283                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3284                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3285                              <1> ;                        / to 1f
  3286                              <1> ;       br      4f
  3287                              <1> ;1:
  3288                              <1> ;       bit     $20000,rkcs
  3289                              <1> ;       beq     4f / wait for seek complete
  3290                              <1> ;       mov     $0b,0b-2
  3291                              <1> ;       mov     rkap,r1
  3292                              <1> ;2:
  3293                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3294                              <1> ;                          / the disk buffer
  3295                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3296                              <1> ;       inc     r1
  3297                              <1> ;       asr     (r1)
  3298                              <1> ;       asr     (r1)
  3299                              <1> ;       asr     (r1) / reissue request
  3300                              <1> ;       dec     r1
  3301                              <1> ;3:
  3302                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3303                              <1> ;       mov     ac,-(sp)
  3304                              <1> ;       mov     mq,-(sp) / put these on the stack
  3305                              <1> ;       mov     sc,-(sp)
  3306                              <1> ;       jsr     r0,poke
  3307                              <1> ;       mov     (sp)+,sc
  3308                              <1> ;       mov     (sp)+,mq / pop them off stack
  3309                              <1> ;       mov     (sp)+,ac
  3310                              <1> ;4:
  3311                              <1> ;       jmp     retisp / u4-3
  3312                              <1> ;
  3313                              <1> ;trapt:                  / r2 points to the
  3314                              <1> ;       mov     (r0)+,r2 / device control register
  3315                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3316                              <1> ;       tst     (sp)+
  3317                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3318                              <1> ;       bge     4b / device still active so branch
  3319                              <1> ;       bit     (r0),active / was device busy?
  3320                              <1> ;       beq     4b / no, stray interrupt
  3321                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3322                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3323                              <1> ;       bge     2f / if no error jump to 2f
  3324                              <1> ;       tst     (r0)+ / skip on error
  3325                              <1> ; 2:
  3326                              <1> ;       jmp     (r0)
  2054                                  %include 'u9.s'        ; 29/06/2015
  2055                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYS9.INC
  2056                              <1> ; Last Modification: 27/02/2022
  2057                              <1> ; ----------------------------------------------------------------------------
  2058                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2059                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2060                              <1> ;
  2061                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2062                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2063                              <1> ; <Bell Laboratories (17/3/1972)>
  2064                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2065                              <1> ;
  2066                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2067                              <1> ;
  2068                              <1> ; ****************************************************************************
  2069                              <1> ; 21/11/2015
  2070                              <1> 
  2071                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2072                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2073                              <1> 
  2074                              <1> getch:
  2075                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2076                              <1> 	; 30/06/2015
  2077                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2078 00005F75 28C0                <1> 	sub	al, al ; 0
  2079                              <1> getch_q: ; 06/08/2015
  2080 00005F77 8A25[166B0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2081 00005F7D EB06                <1>         jmp     short getc_n
  2082                              <1> 
  2083                              <1> getc: 
  2084                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2085                              <1> 	; 12/11/2015
  2086                              <1> 	; 15/09/2015
  2087                              <1> 	; 01/07/2015
  2088                              <1> 	; 30/06/2015
  2089                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2090                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2091                              <1> 	;
  2092                              <1> 	; Retro UNIX 8086 v1 modification !
  2093                              <1> 	; 
  2094                              <1> 	; 'getc' gets (next) character 
  2095                              <1> 	;	 from requested TTY (keyboard) buffer 
  2096                              <1> 	; INPUTS ->
  2097                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2098                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2099                              <1> 	;	(Keyboard buffer will point to 
  2100                              <1> 	;			next character at next call)
  2101                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2102                              <1> 	;	(Keyboard buffer will point to 
  2103                              <1> 	;			current character at next call)
  2104                              <1> 	; OUTPUTS ->
  2105                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2106                              <1> 	;     			 ZF=0 -> AX has (current) character
  2107                              <1> 	;      AL = ascii code
  2108                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2109                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2110                              <1> 	; Original UNIX V1 'getc': 
  2111                              <1> 	;		get a character off character list
  2112                              <1> 	;
  2113                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2114                              <1> 	;
  2115                              <1> 	; 30/06/2015 (32 bit modifications)
  2116                              <1> 	; 16/07/2013
  2117                              <1> 	; mov 	[getctty], ah
  2118                              <1> 	;
  2119                              <1> 
  2120 00005F7F 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2121                              <1> getc_n:
  2122                              <1> 	; 30/06/2015
  2123 00005F85 08E4                <1> 	or	ah, ah
  2124 00005F87 740D                <1> 	jz	short getc0 
  2125 00005F89 D0E4                <1> 	shl	ah, 1
  2126 00005F8B 0FB6DC              <1> 	movzx	ebx, ah
  2127 00005F8E 81C3[186B0000]      <1> 	add	ebx, ttychr
  2128 00005F94 EB05                <1> 	jmp	short getc1
  2129                              <1> getc0:
  2130 00005F96 BB[186B0000]        <1> 	mov	ebx, ttychr
  2131                              <1> getc1:
  2132 00005F9B 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2133                              <1> 				; (by kb_int)	
  2134 00005F9E 6609C9              <1> 	or	cx, cx
  2135 00005FA1 7507                <1> 	jnz	short getc2
  2136 00005FA3 20C0                <1> 	and 	al, al
  2137 00005FA5 7415                <1> 	jz	short getc_s
  2138                              <1> 	;xor	ax, ax
  2139                              <1> 	; 24/12/2021
  2140 00005FA7 31C0                <1> 	xor	eax, eax
  2141 00005FA9 C3                  <1> 	retn
  2142                              <1> getc2:	
  2143 00005FAA 20C0                <1> 	and	al, al
  2144 00005FAC 6689C8              <1> 	mov	ax, cx
  2145 00005FAF 66B90000            <1> 	mov	cx, 0
  2146 00005FB3 7506                <1> 	jnz	short getc3
  2147                              <1> getc_sn:
  2148 00005FB5 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2149 00005FB8 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2150                              <1> getc3:
  2151 00005FBB C3                  <1> 	retn
  2152                              <1> getc_s:
  2153                              <1> 	; 12/11/2015
  2154                              <1> 	; 15/09/2015
  2155                              <1> 	; 01/07/2015
  2156                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2157                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2158                              <1> 	;
  2159                              <1> 	; tty  of the current process is not 
  2160                              <1> 	; current tty (ptty); so, current process only 
  2161                              <1> 	; can use keyboard input when its tty becomes 
  2162                              <1> 	; current tty (ptty).
  2163                              <1> 	; 'sleep' is for preventing an endless lock
  2164                              <1> 	; during this tty input request.
  2165                              <1> 	; (Because, the user is not looking at the video page
  2166                              <1> 	; of the process to undersand there is a keyboard
  2167                              <1> 	; input request.)
  2168                              <1> 	;
  2169                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2170                              <1> 	;
  2171                              <1> 	; 05/10/2013
  2172                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2173                              <1> 	;
  2174                              <1> 	; 10/10/2013
  2175                              <1> gcw0:
  2176 00005FBC B10A                <1> 	mov	cl, 10 ; ch = 0
  2177                              <1> gcw1:	
  2178                              <1> 	; 12/11/2015
  2179 00005FBE E827DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2180                              <1> 	; 10/10/2013
  2181 00005FC3 E86EEFFFFF          <1> 	call	idle
  2182 00005FC8 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2183                              <1> 				; (by kb_int)
  2184 00005FCB 6609C0              <1> 	or	ax, ax
  2185                              <1> ;	jnz	short gcw3
  2186 00005FCE 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2187                              <1> 	; 30/06/2015
  2188 00005FD0 FEC9                <1> 	dec	cl
  2189 00005FD2 75EA                <1> 	jnz	short gcw1
  2190                              <1> 	;
  2191 00005FD4 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2192                              <1> ;	; 10/12/2013
  2193                              <1> ;	cmp 	ah, [ptty]
  2194                              <1> ;	jne	short gcw2
  2195                              <1> ;	; 14/02/2014
  2196                              <1> ;	cmp	byte [u.uno], 1
  2197                              <1> ;	jna	short gcw0		
  2198                              <1> ;gcw2:
  2199 00005FDA E8E4EFFFFF          <1> 	call	sleep
  2200                              <1> 	;
  2201                              <1> 	; 20/09/2013
  2202 00005FDF 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn]
  2203 00005FE5 30C0                <1> 	xor 	al, al
  2204 00005FE7 EB9C                <1> 	jmp	short getc_n
  2205                              <1> ;gcw3:
  2206                              <1> gcw2: 	; 15/09/2015
  2207                              <1> 	; 10/10/2013
  2208 00005FE9 30C9                <1> 	xor	cl, cl
  2209 00005FEB EBC8                <1> 	jmp	short getc_sn
  2210                              <1> 
  2211                              <1> putc:	
  2212                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2213                              <1> 	; 13/08/2015
  2214                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2215                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2216                              <1> 	;
  2217                              <1> 	; Retro UNIX 8086 v1 modification !
  2218                              <1> 	; 
  2219                              <1> 	; 'putc' puts a character 
  2220                              <1> 	;	 onto requested (tty) video page or
  2221                              <1> 	;	 serial port
  2222                              <1> 	; INPUTS ->
  2223                              <1> 	;     AL = ascii code of the character
  2224                              <1> 	;     AH = video page (tty) number (0 to 7)
  2225                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2226                              <1> 	; OUTPUTS ->
  2227                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2228                              <1> 	;      			ZF=0 -> AX has (current) character
  2229                              <1> 	;     cf=0 and AH = 0 -> no error
  2230                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2231                              <1> 	; 
  2232                              <1> 	; Original UNIX V1 'putc': 
  2233                              <1> 	;     put a character at the end of character list
  2234                              <1> 	;
  2235                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2236                              <1> 	;
  2237 00005FED 80FC07              <1> 	cmp	ah, 7
  2238                              <1>         ;ja	sndc
  2239 00005FF0 770A                <1>         ja      short sndc ; 24/12/2024
  2240                              <1> 	; 30/06/2015
  2241 00005FF2 0FB6DC              <1> 	movzx	ebx, ah
  2242                              <1> 	; 13/08/2015
  2243 00005FF5 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2244 00005FF7 E9E3B3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2245                              <1> 
  2246                              <1> sndc:   ; <Send character>
  2247                              <1> 	;
  2248                              <1> 	; 12/01/2022
  2249                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2250                              <1> 	; 17/11/2015
  2251                              <1> 	; 16/11/2015
  2252                              <1> 	; 11/11/2015
  2253                              <1> 	; 10/11/2015
  2254                              <1> 	; 09/11/2015
  2255                              <1> 	; 08/11/2015
  2256                              <1> 	; 07/11/2015
  2257                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2258                              <1> 	; 29/10/2015
  2259                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2260                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2261                              <1> 	;
  2262                              <1> 	; Retro UNIX 8086 v1 feature only !
  2263                              <1> 	;
  2264                              <1> 	; ah = [u.ttyn]
  2265                              <1> 	;
  2266                              <1> 	; 30/06/2015
  2267 00005FFC 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2268                              <1> 	; 07/11/2015
  2269 00005FFF 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2270                              <1> sndc0:
  2271                              <1> 	; 07/11/2015
  2272 00006002 E80AF0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2273 00006007 7405                <1> 	jz	short sndc1
  2274 00006009 E8DCDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2275                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2276                              <1> sndc1:
  2277                              <1> 	; 16/11/2015
  2278                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2279                              <1> 	; 24/12/2021
  2280 0000600E 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2281                              <1> sndcx:
  2282 00006010 8A83[5A6B0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2283 00006016 8AA3[586B0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2284                              <1> 	;
  2285                              <1> 	; 17/11/2015
  2286                              <1> 	; check 'request for response' status
  2287 0000601C 80BB[546B0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2288 00006023 740A                <1> 	jz	short query
  2289                              <1> response:
  2290 00006025 FE05[576B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2291 0000602B B0FF                <1> 	mov	al, 0FFh	 
  2292 0000602D EB14                <1> 	jmp	short sndc3
  2293                              <1> query:
  2294 0000602F 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2295 00006031 750E                <1> 	jnz 	short sndc2 ; normal character
  2296                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2297                              <1> 	;je	short sndc2  ; yes, already responded
  2298                              <1> 	; 16/11/2015
  2299                              <1> 	; query: request for response (again)
  2300 00006033 8883[586B0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2301 00006039 FE05[576B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2302 0000603F EB02                <1> 	jmp	short sndc3
  2303                              <1> sndc2:
  2304 00006041 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2305                              <1> sndc3:
  2306 00006043 8883[5A6B0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2307 00006049 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2308                              <1> 	; 30/06/2015
  2309 0000604B E83ED5FFFF          <1> 	call	sp_status ; get serial port status
  2310                              <1> 	; AL = Line status, AH = Modem status
  2311                              <1> 	; 07/11/2015
  2312 00006050 A880                <1> 	test	al, 80h
  2313 00006052 7504                <1> 	jnz	short sndc4
  2314 00006054 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2315 00006056 751A                <1> 	jnz	short sndc5
  2316                              <1> sndc4: 	; Check line status again
  2317                              <1> 	; 16/11/2015
  2318                              <1> 	;push	cx
  2319                              <1> 	; 24/12/2021
  2320 00006058 51                  <1> 	push	ecx
  2321                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2322                              <1> 	; 12/01/2022
  2323 00006059 31C9                <1> 	xor	ecx, ecx
  2324 0000605B B106                <1> 	mov	cl, 6
  2325 0000605D E874B4FFFF          <1> 	call	WAITF
  2326                              <1> 	;pop	cx
  2327                              <1> 	; 24/12/1021
  2328 00006062 59                  <1> 	pop	ecx
  2329                              <1> 	;
  2330 00006063 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2331 00006065 E824D5FFFF          <1> 	call	sp_status ; get serial port status
  2332                              <1> 	; 16/11/2015
  2333                              <1> 	; 09/11/2015
  2334                              <1> 	; 08/11/2015
  2335 0000606A A880                <1> 	test	al, 80h	; time out error
  2336 0000606C 7565                <1>         jnz     short sndc7
  2337 0000606E A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2338 00006070 7461                <1>         jz	short sndc7
  2339                              <1> sndc5:  
  2340 00006072 8A83[5A6B0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2341 00006078 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2342 0000607C 28DE                <1> 	sub	dh, bl
  2343 0000607E EE                  <1> 	out	dx, al	   ; send on serial port
  2344                              <1> 	; 10/11/2015
  2345                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2346                              <1> 	; (to improve text flow to the terminal)
  2347                              <1> 	; ('diskette.inc': 'WAITF')
  2348                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2349                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2350                              <1> 	;push	cx
  2351                              <1> 	; 24/12/2021
  2352 0000607F 51                  <1> 	push	ecx
  2353                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2354                              <1> 	; 12/01/2022
  2355 00006080 29C9                <1> 	sub	ecx, ecx
  2356 00006082 B106                <1> 	mov	cl, 6
  2357 00006084 E84DB4FFFF          <1> 	call	WAITF
  2358                              <1> 	;pop	cx
  2359                              <1> 	; 24/12/1021
  2360 00006089 59                  <1> 	pop	ecx
  2361                              <1>     	;
  2362                              <1> 	; 07/11/2015
  2363 0000608A 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2364                              <1> 	;
  2365 0000608C E8FDD4FFFF          <1> 	call	sp_status ; get serial port status
  2366                              <1> 	; AL = Line status, AH = Modem status
  2367                              <1> 	;
  2368 00006091 E87BEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2369 00006096 7405                <1> 	jz	short sndc6
  2370 00006098 E84DDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2371                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2372                              <1> sndc6:
  2373 0000609D 3C80                <1> 	cmp	al, 80h
  2374 0000609F 7332                <1> 	jnb	short sndc7		
  2375                              <1> 	;
  2376 000060A1 803D[576B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2377 000060A8 7244                <1> 	jb	short sndc8 	; no, normal character
  2378 000060AA 883D[576B0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2379                              <1> 	; 17/11/2015
  2380 000060B0 E881EEFFFF          <1> 	call	idle
  2381                              <1> 	;
  2382 000060B5 38BB[5A6B0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2383                              <1>         ;ja	sndc2       ; response (will be followed by
  2384                              <1> 			    ; a normal character)
  2385                              <1> 	; 24/12/2021
  2386 000060BB 7602                <1> 	jna	short sndc_10
  2387 000060BD EB82                <1> 	jmp	sndc2
  2388                              <1> sndc_10:
  2389                              <1> 	; Query request must be responded by the terminal
  2390                              <1> 	; before sending a normal character !
  2391 000060BF 53                  <1> 	push	ebx
  2392                              <1> 	;push	cx ; *** cl = character (to be sent)
  2393                              <1> 	; 24/12/2021
  2394 000060C0 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2395 000060C1 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn]
  2396 000060C7 E8F7EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2397                              <1> 		      ; received data available interrupt
  2398                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2399                              <1> 	; 24/12/2021
  2400 000060CC 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2401 000060CD 5B                  <1> 	pop	ebx
  2402 000060CE E93DFFFFFF          <1>         jmp	sndcx
  2403                              <1> sndc7:
  2404                              <1> 	 ; 16/11/2015
  2405 000060D3 803D[576B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2406 000060DA 7213                <1> 	jb	short sndc9 	; no
  2407                              <1> 	;
  2408 000060DC 88BB[586B0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2409 000060E2 88BB[5A6B0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2410                              <1> 	;
  2411 000060E8 883D[576B0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2412                              <1> sndc8:
  2413 000060EE F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2414                              <1> sndc9:
  2415                              <1> 	; AL = Line status, AH = Modem status
  2416 000060EF C3                  <1> 	retn
  2417                              <1> 
  2418                              <1> get_cpos:
  2419                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2420                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2421                              <1> 	;
  2422                              <1> 	; INPUT -> bl = video page number
  2423                              <1> 	; RETURN -> dx = cursor position
  2424                              <1> 
  2425 000060F0 53                  <1> 	push	ebx
  2426 000060F1 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2427 000060F4 D0E3                <1> 	shl	bl, 1
  2428 000060F6 81C3[066B0000]      <1> 	add	ebx, cursor_posn
  2429 000060FC 668B13              <1> 	mov	dx, [ebx]
  2430 000060FF 5B                  <1> 	pop	ebx
  2431 00006100 C3                  <1> 	retn
  2432                              <1> 
  2433                              <1> read_ac_current:
  2434                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2435                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2436                              <1> 	;
  2437                              <1> 	; INPUT -> bl = video page number
  2438                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2439                              <1> 
  2440 00006101 E843B4FFFF          <1> 	call 	find_position ; 'video.inc'
  2441                              <1> 	; dx = status port
  2442                              <1> 	; esi = cursor location/address
  2443 00006106 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2444 0000610C 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2445 0000610F C3                  <1> 	retn
  2446                              <1> 
  2447                              <1> syssleep:
  2448                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2449                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2450                              <1> 	;
  2451                              <1> 	; Retro UNIX 8086 v1 feature only
  2452                              <1> 	; (INPUT -> none)
  2453                              <1> 	;
  2454 00006110 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2455 00006117 8AA3[076C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2456 0000611D E8A1EEFFFF          <1> 	call	sleep
  2457 00006122 E9DFD9FFFF          <1> 	jmp	sysret
  2458                              <1> 
  2459                              <1> 	; 27/02/2022
  2460                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2461                              <1> %if 0
  2462                              <1> 
  2463                              <1> vp_clr:
  2464                              <1> 	; Reset/Clear Video Page
  2465                              <1> 	;
  2466                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2467                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2468                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2469                              <1> 	;
  2470                              <1> 	; Retro UNIX 8086 v1 feature only !
  2471                              <1> 	;
  2472                              <1> 	; INPUTS -> 
  2473                              <1> 	;   BL = video page number	 
  2474                              <1> 	;
  2475                              <1> 	; OUTPUT ->
  2476                              <1> 	;   none
  2477                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2478                              <1> 	;
  2479                              <1> 	; 04/12/2013
  2480                              <1> 	sub	al, al
  2481                              <1> 	; al = 0 (clear video page)
  2482                              <1> 	; bl = video page
  2483                              <1> 	mov	ah, 07h
  2484                              <1> 	; ah = 7 (attribute/color)
  2485                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2486                              <1> 	; 24/12/2021
  2487                              <1> 	xor	ecx, ecx
  2488                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2489                              <1> 	call	scroll_up
  2490                              <1> 	; bl = video page
  2491                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2492                              <1> 	; 24/12/2021
  2493                              <1> 	xor	edx, edx 
  2494                              <1> 	jmp 	set_cpos
  2495                              <1> 
  2496                              <1> %endif
  2497                              <1> 
  2498                              <1> sysmsg:
  2499                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2500                              <1> 	; 11/11/2015
  2501                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2502                              <1> 	; Print user-application message on user's console tty
  2503                              <1> 	;
  2504                              <1> 	; Input -> EBX = Message address
  2505                              <1> 	;	   ECX = Message length (max. 255)
  2506                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2507                              <1> 	;
  2508 00006127 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2509                              <1> 	;ja	sysret ; nothing to do with big message size
  2510 0000612D 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2511 0000612F 08C9                <1> 	or	cl, cl
  2512                              <1> 	;jz	sysret
  2513 00006131 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2514 00006133 20D2                <1> 	and	dl, dl
  2515 00006135 7502                <1> 	jnz	short sysmsg0
  2516 00006137 B207                <1> 	mov	dl, 07h ; default color
  2517                              <1> 		; (black background, light gray character)
  2518                              <1> sysmsg0:
  2519 00006139 891D[CC6E0000]      <1> 	mov	[u.base], ebx
  2520 0000613F 8815[176B0000]      <1> 	mov	[ccolor], dl ; color attributes
  2521 00006145 89E5                <1> 	mov	ebp, esp
  2522 00006147 31DB                <1> 	xor	ebx, ebx ; 0
  2523 00006149 891D[D46E0000]      <1> 	mov	[u.nread], ebx ; 0
  2524                              <1> 	;
  2525 0000614F 381D[0D6F0000]      <1> 	cmp	[u.kcall], bl ; 0
  2526 00006155 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2527                              <1> 	;
  2528 00006157 890D[D06E0000]      <1> 	mov	[u.count], ecx
  2529 0000615D 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2530                              <1> 	; 24/12/2021
  2531                              <1> 	; (dword alignment for esp)
  2532 0000615E F6C103              <1> 	test	cl, 3
  2533 00006161 7404                <1> 	jz	short sysmsg_7
  2534 00006163 80C903              <1> 	or	cl, 3
  2535 00006166 41                  <1> 	inc	ecx
  2536                              <1> sysmsg_7:
  2537 00006167 29CC                <1> 	sub	esp, ecx
  2538 00006169 89E7                <1> 	mov	edi, esp
  2539 0000616B 89E6                <1> 	mov	esi, esp
  2540 0000616D 66891D[0B6F0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2541                              <1> 	; 11/11/2015
  2542 00006174 8A25[DC6E0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2543                              <1> 	; 0 = none
  2544 0000617A FECC                <1> 	dec	ah
  2545 0000617C 790C                <1> 	jns	short sysmsg1 
  2546 0000617E 8A1D[F56E0000]      <1> 	mov	bl, [u.uno] ; process number	
  2547 00006184 8AA3[076C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2548                              <1> sysmsg1:
  2549 0000618A 8825[FA6E0000]      <1> 	mov	[u.ttyn], ah
  2550                              <1> sysmsg2:
  2551 00006190 E884F5FFFF          <1> 	call	cpass
  2552 00006195 7416                <1> 	jz	short sysmsg5
  2553 00006197 AA                  <1> 	stosb
  2554 00006198 20C0                <1> 	and	al, al
  2555 0000619A 75F4                <1> 	jnz	short sysmsg2
  2556                              <1> sysmsg3:
  2557 0000619C 80FC07              <1> 	cmp	ah, 7 ; tty number
  2558 0000619F 7711                <1> 	ja	short sysmsg6 ; serial port
  2559 000061A1 E83E000000          <1> 	call	print_cmsg
  2560                              <1> sysmsg4:
  2561 000061A6 89EC                <1> 	mov	esp, ebp	
  2562                              <1> sysmsg8: ; 24/12/2021	
  2563 000061A8 E959D9FFFF          <1> 	jmp	sysret
  2564                              <1> sysmsg5:
  2565 000061AD C60700              <1> 	mov	byte [edi], 0
  2566 000061B0 EBEA                <1> 	jmp	short sysmsg3
  2567                              <1> sysmsg6:
  2568 000061B2 8A06                <1> 	mov	al, [esi]
  2569 000061B4 E843FEFFFF          <1> 	call	sndc
  2570 000061B9 72EB                <1> 	jc	short sysmsg4
  2571 000061BB 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2572 000061BE 76E6                <1> 	jna	short sysmsg4
  2573 000061C0 46                  <1> 	inc 	esi
  2574 000061C1 8A25[FA6E0000]      <1> 	mov	ah, [u.ttyn]
  2575 000061C7 EBE9                <1> 	jmp	short sysmsg6
  2576                              <1> 
  2577                              <1> sysmsgk: ; Temporary (01/07/2015)
  2578                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2579                              <1> 	; (ECX -character count- will not be considered)
  2580 000061C9 8B35[CC6E0000]      <1> 	mov	esi, [u.base]
  2581 000061CF 8A25[166B0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2582 000061D5 8825[FA6E0000]      <1> 	mov	[u.ttyn], ah
  2583 000061DB C605[0D6F0000]00    <1> 	mov	byte [u.kcall], 0
  2584 000061E2 EBB8                <1> 	jmp	short sysmsg3
  2585                              <1> 	
  2586                              <1> print_cmsg: 
  2587                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2588                              <1> 	;
  2589                              <1> 	; print message (on user's console tty) 
  2590                              <1> 	;	with requested color
  2591                              <1> 	;
  2592                              <1> 	; INPUTS:
  2593                              <1> 	;	esi = message address
  2594                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2595                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2596                              <1> 	;
  2597 000061E4 AC                  <1> 	lodsb
  2598                              <1> pcmsg1:
  2599 000061E5 56                  <1> 	push 	esi
  2600 000061E6 0FB61D[FA6E0000]    <1>         movzx   ebx, byte [u.ttyn]
  2601 000061ED 8A25[176B0000]      <1> 	mov	ah, [ccolor]
  2602 000061F3 E8E7B1FFFF          <1> 	call 	write_tty
  2603 000061F8 5E                  <1> 	pop	esi
  2604 000061F9 AC                  <1> 	lodsb
  2605 000061FA 20C0                <1> 	and 	al, al  ; 0
  2606 000061FC 75E7                <1> 	jnz 	short pcmsg1
  2607 000061FE C3                  <1> 	retn
  2608                              <1> 
  2609                              <1> sysgeterr:
  2610                              <1> 	; 16/02/2022
  2611                              <1> 	; 09/12/2015
  2612                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2613                              <1> 	; Get last error number or page fault count
  2614                              <1> 	; (for debugging)
  2615                              <1> 	;
  2616                              <1> 	; Input -> EBX = return type
  2617                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2618                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2619                              <1> 	;	   FFFFFFFEh = total page fault count
  2620                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2621                              <1> 	;
  2622                              <1> 	; Output -> EAX = last error number or page fault count
  2623                              <1> 	;	   (depending on EBX input)
  2624                              <1> 	; 	
  2625 000061FF 21DB                <1> 	and 	ebx, ebx
  2626 00006201 750F                <1> 	jnz	short glerr_2
  2627                              <1> glerr_0:
  2628 00006203 A1[FB6E0000]        <1> 	mov	eax, [u.error]
  2629                              <1> glerr_1:
  2630 00006208 A3[AC6E0000]        <1> 	mov	[u.r0], eax
  2631                              <1>  	;retn
  2632                              <1> 	; 16/02/2022 (BugFix)
  2633 0000620D E9F4D8FFFF          <1> 	jmp	sysret
  2634                              <1> glerr_2:
  2635 00006212 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2636 00006213 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2637 00006215 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2638 00006216 75EB                <1> 	jnz	short glerr_0
  2639 00006218 A1[A06B0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2640 0000621D EBE9                <1>         jmp     short glerr_1
  2641                              <1> glerr_3:
  2642 0000621F A1[0F6F0000]        <1> 	mov 	eax, [u.pfcount]
  2643 00006224 EBE2                <1> 	jmp	short glerr_1
  2055                                  
  2056                                  ; 07/03/2015
  2057                                  ; Temporary Code
  2058                                  display_disks:
  2059 00006226 803D[DE650000]00        	cmp 	byte [fd0_type], 0
  2060 0000622D 7605                    	jna 	short ddsks1
  2061 0000622F E87D000000              	call	pdskm
  2062                                  ddsks1:
  2063 00006234 803D[DF650000]00        	cmp	byte [fd1_type], 0
  2064 0000623B 760C                    	jna	short ddsks2
  2065 0000623D C605[CD670000]31        	mov	byte [dskx], '1'
  2066 00006244 E868000000              	call	pdskm
  2067                                  ddsks2:
  2068 00006249 803D[E0650000]00        	cmp	byte [hd0_type], 0
  2069 00006250 7654                    	jna	short ddsk6
  2070 00006252 66C705[CB670000]68-     	mov	word [dsktype], 'hd'
  2070 0000625A 64                 
  2071 0000625B C605[CD670000]30        	mov	byte [dskx], '0'
  2072 00006262 E84A000000              	call	pdskm
  2073                                  ddsks3:
  2074 00006267 803D[E1650000]00        	cmp	byte [hd1_type], 0
  2075 0000626E 7636                    	jna	short ddsk6
  2076 00006270 C605[CD670000]31        	mov	byte [dskx], '1'
  2077 00006277 E835000000              	call	pdskm
  2078                                  ddsks4:
  2079 0000627C 803D[E2650000]00        	cmp	byte [hd2_type], 0
  2080 00006283 7621                    	jna	short ddsk6
  2081 00006285 C605[CD670000]32        	mov	byte [dskx], '2'
  2082 0000628C E820000000              	call	pdskm
  2083                                  ddsks5:
  2084 00006291 803D[E3650000]00        	cmp	byte [hd3_type], 0
  2085 00006298 760C                    	jna	short ddsk6
  2086 0000629A C605[CD670000]33        	mov	byte [dskx], '3'
  2087 000062A1 E80B000000              	call	pdskm
  2088                                  ddsk6:
  2089 000062A6 BE[DC670000]            	mov	esi, nextline
  2090 000062AB E806000000              	call	pdskml
  2091                                  pdskm_ok:
  2092 000062B0 C3                      	retn
  2093                                  pdskm:
  2094 000062B1 BE[C9670000]            	mov	esi, dsk_ready_msg
  2095                                  pdskml:	
  2096 000062B6 AC                      	lodsb
  2097 000062B7 08C0                    	or	al, al
  2098 000062B9 74F5                    	jz	short pdskm_ok
  2099 000062BB 56                      	push	esi
  2100 000062BC 31DB                    	xor	ebx, ebx ; 0
  2101                                  			; Video page 0 (bl=0)
  2102 000062BE B407                    	mov	ah, 07h ; Black background, 
  2103                                  			; light gray forecolor
  2104 000062C0 E81AB1FFFF              	call	write_tty
  2105 000062C5 5E                      	pop	esi
  2106 000062C6 EBEE                    	jmp	short pdskml
  2107                                  
  2108 000062C8 90<rep 8h>              align 16
  2109                                  
  2110                                  gdt:	; Global Descriptor Table
  2111                                  	; (30/07/2015, conforming cs)
  2112                                  	; (26/03/2015)
  2113                                  	; (24/03/2015, tss)
  2114                                  	; (19/03/2015)
  2115                                  	; (29/12/2013)
  2116                                  	;
  2117 000062D0 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2118                                  	; 18/08/2014
  2119                                  			; 8h kernel code segment, base = 00000000h		
  2120 000062D8 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2121                                  			; 10h kernel data segment, base = 00000000h	
  2122 000062E0 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2123                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2124 000062E8 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2125                                  			; 23h user data segment, base address = 400000h ; CORE
  2126 000062F0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2127                                  			; Task State Segment
  2128 000062F8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2129                                  			       ;  no IO permission in ring 3)
  2130                                  gdt_tss0:
  2131 000062FA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2132                                  gdt_tss1:
  2133 000062FC 00                      	db 0  ; TSS base address, bits 16-23 
  2134                                  	      		; 49h	
  2135 000062FD E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2136 000062FE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2137                                  gdt_tss2:
  2138 000062FF 00                      	db 0  ; TSS base address, bits 24-31 
  2139                                  
  2140                                  gdt_end:
  2141                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2142                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2143                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2144                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2145                                  
  2146                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2147                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2148                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2149                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2150                                  		; W= Writeable, A= Accessed
  2151                                  	
  2152                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2153                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2154                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2155                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2156                                  
  2157                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2158                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2159                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2160                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2161                                  	
  2162                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2163                                  
  2164                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2165                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2166                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2167                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2168                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2169                                  		; AVL= Available to programmers	
  2170                                  
  2171                                  gdtd:
  2172 00006300 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2173 00006302 [D0620000]                      dd gdt			; Address of the GDT
  2174                                  
  2175                                  	; 20/08/2014
  2176                                  idtd:
  2177 00006306 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2178 00006308 [80680000]                      dd idt			; Address of the IDT
  2179                                  
  2180                                  Align 4
  2181                                  
  2182                                  	; 21/08/2014
  2183                                  ilist:
  2184                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2185                                  	;
  2186                                  	; Exception list
  2187                                  	; 25/08/2014	
  2188 0000630C [3C080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2189 00006310 [43080000]              	dd	exc1	
  2190 00006314 [4A080000]              	dd 	exc2	
  2191 00006318 [51080000]              	dd	exc3	
  2192 0000631C [55080000]              	dd	exc4	
  2193 00006320 [59080000]              	dd	exc5	
  2194 00006324 [5D080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2195 00006328 [61080000]              	dd	exc7	
  2196 0000632C [65080000]              	dd	exc8	
  2197 00006330 [69080000]              	dd	exc9	
  2198 00006334 [6D080000]              	dd 	exc10	
  2199 00006338 [71080000]              	dd	exc11
  2200 0000633C [75080000]              	dd	exc12
  2201 00006340 [79080000]              	dd	exc13	; 0Dh, General Protection Fault
  2202 00006344 [7D080000]              	dd 	exc14	; 0Eh, Page Fault
  2203 00006348 [81080000]              	dd	exc15
  2204 0000634C [85080000]              	dd	exc16
  2205 00006350 [89080000]              	dd	exc17
  2206 00006354 [8D080000]              	dd 	exc18
  2207 00006358 [91080000]              	dd	exc19
  2208 0000635C [95080000]              	dd 	exc20
  2209 00006360 [99080000]              	dd	exc21
  2210 00006364 [9D080000]              	dd	exc22
  2211 00006368 [A1080000]              	dd	exc23
  2212 0000636C [A5080000]              	dd 	exc24
  2213 00006370 [A9080000]              	dd	exc25
  2214 00006374 [AD080000]              	dd	exc26
  2215 00006378 [B1080000]              	dd	exc27
  2216 0000637C [B5080000]              	dd 	exc28
  2217 00006380 [B9080000]              	dd	exc29
  2218 00006384 [BD080000]              	dd 	exc30
  2219 00006388 [C1080000]              	dd	exc31
  2220                                  	; Interrupt list
  2221 0000638C [78060000]              	dd	timer_int	; INT 20h
  2222                                  		;dd	irq0	
  2223 00006390 [7D0B0000]              	dd	keyb_int	; 27/08/2014
  2224                                  		;dd	irq1
  2225 00006394 [96070000]              	dd	irq2
  2226                                  		; COM2 int
  2227 00006398 [9A070000]              	dd	irq3
  2228                                  		; COM1 int
  2229 0000639C [A5070000]              	dd	irq4
  2230 000063A0 [B0070000]              	dd	irq5
  2231                                  ;DISKETTE_INT: ;06/02/2015
  2232 000063A4 [67250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2233                                  		;dd	irq6
  2234                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2235                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2236 000063A8 [2C0B0000]              	dd	default_irq7	; 25/02/2015
  2237                                  		;dd	irq7
  2238                                  ; Real Time Clock Interrupt
  2239 000063AC [CA090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2240                                  		;dd	irq8	; INT 28h
  2241 000063B0 [C0070000]              	dd	irq9
  2242 000063B4 [C4070000]              	dd	irq10
  2243 000063B8 [C8070000]              	dd	irq11
  2244 000063BC [CC070000]              	dd	irq12
  2245 000063C0 [D0070000]              	dd	irq13
  2246                                  ;HDISK_INT1:  ;06/02/2015 	
  2247 000063C4 [8D2D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2248                                  		;dd	irq14
  2249                                  ;HDISK_INT2:  ;06/02/2015
  2250 000063C8 [B02D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2251                                  		;dd	irq15	; INT 2Fh
  2252                                  		; 14/08/2015
  2253 000063CC [EE390000]              	dd	sysent		; INT 30h (system calls)
  2254                                  	
  2255                                  	;dd	ignore_int
  2256 000063D0 00000000                	dd	0
  2257                                  
  2258                                  ;;;
  2259                                  ;;; 11/03/2015
  2260                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2261                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2262                              <1> ; Last Modification: 11/03/2015
  2263                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2264                              <1> ;
  2265                              <1> ; ///////// KEYBOARD DATA ///////////////
  2266                              <1> 
  2267                              <1> ; 05/12/2014
  2268                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2269                              <1> ; 03/06/86  KEYBOARD BIOS
  2270                              <1> 
  2271                              <1> ;---------------------------------------------------------------------------------
  2272                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2273                              <1> ;---------------------------------------------------------------------------------
  2274                              <1> 
  2275                              <1> ;-----	TABLES FOR ALT CASE ------------
  2276                              <1> ;-----	ALT-INPUT-TABLE 
  2277 000063D4 524F50514B          <1> K30:	db	82,79,80,81,75
  2278 000063D9 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2279                              <1> ;-----	SUPER-SHIFT-TABLE 
  2280 000063DE 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2281 000063E4 161718191E1F        <1> 	db	22,23,24,25,30,31
  2282 000063EA 202122232425        <1> 	db	32,33,34,35,36,37
  2283 000063F0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2284 000063F6 3132                <1> 	db	49,50
  2285                              <1> 
  2286                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2287                              <1> ;-----	KEY_TABLE 
  2288 000063F8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2289 000063F9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2290 000063FE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2291                              <1> _K6L    equ     $-_K6
  2292                              <1> 
  2293                              <1> ;-----	MASK_TABLE
  2294 00006400 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2295 00006401 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2296 00006406 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2297                              <1> 
  2298                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2299 00006408 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2300 0000640E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2301 00006414 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2302 0000641A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2303 00006420 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2304 00006426 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2305 0000642C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2306 00006432 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2307 00006438 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2308 0000643E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2309                              <1> 	;				;----- FUNCTIONS ------		
  2310 00006442 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2311 00006448 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2312 0000644E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2313 00006454 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2314 0000645A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2315                              <1> 
  2316                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2317 00006460 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2317 00006469 39302D3D0809        <1>
  2318 0000646F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2318 00006478 705B5D0DFF61736466- <1>
  2318 00006481 67686A6B6C3B27      <1>
  2319 00006488 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2319 00006491 6D2C2E2FFF2AFF20FF  <1>
  2320                              <1> ;-----	LC TABLE SCAN
  2321 0000649A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2322 0000649F 4041424344          <1> 	db	64,65,66,67,68
  2323 000064A4 FFFF                <1> 	db	-1,-1			; NL, SL
  2324                              <1> 
  2325                              <1> ;-----	KEYPAD TABLE
  2326 000064A6 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2327 000064AC 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2328 000064B3 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2329                              <1> 
  2330                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2331 000064B8 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2331 000064C1 28295F2B0800        <1>
  2332 000064C7 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2332 000064D0 507B7D0DFF41534446- <1>
  2332 000064D9 47484A4B4C3A22      <1>
  2333 000064E0 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2333 000064E9 4D3C3E3FFF2AFF20FF  <1>
  2334                              <1> ;-----	UC TABLE SCAN
  2335 000064F2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2336 000064F7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2337 000064FC FFFF                <1> 	db	-1,-1			; NL, SL
  2338                              <1> 
  2339                              <1> ;-----	NUM STATE TABLE
  2340 000064FE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2340 00006507 3233302E            <1>
  2341                              <1> 	;
  2342 0000650B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2343                              <1> 
  2344                              <1> Align	4
  2345                              <1> ;----------------------------------------
  2346                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2347                              <1> ;----------------------------------------
  2348 00006510 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2349 00006511 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2350                              <1> 				; (29h default setting for video mode 3)
  2351                              <1> 				; Mode Select register Bits
  2352                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2353                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2354                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2355                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2356                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2357                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2358                              <1> 				;   BIT 6, 7 - Not Used
  2359                              <1> 
  2360                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2361                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2362                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2363                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2364                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2365                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2366                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2367                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2368                              <1> ; Mode & 37h = Video signal OFF
  2369                              <1> 			
  2370                              <1> 
  2371                              <1> ; 26/08/2014
  2372                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2373                              <1> ; Derived from IBM "pc-at" 
  2374                              <1> ; rombios source code (06/10/1985)
  2375                              <1> ; 'dseg.inc'
  2376                              <1> 
  2377                              <1> ;---------------------------------------;
  2378                              <1> ;	SYSTEM DATA AREA		;
  2379                              <1> ;----------------------------------------
  2380 00006512 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2381                              <1> 
  2382                              <1> ;----------------------------------------
  2383                              <1> ;	KEYBOARD DATA AREAS		;
  2384                              <1> ;----------------------------------------
  2385                              <1> 
  2386 00006513 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2387 00006514 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2388 00006515 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2389 00006516 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2390 00006517 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2391 00006518 [28650000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2392 0000651C [48650000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2393 00006520 [28650000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2394 00006524 [28650000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2395                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2396 00006528 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2397                              <1> 
  2398                              <1> ; /// End Of KEYBOARD DATA ///
  2261                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2262                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2263                              <1> ; Last Modification: 11/03/2015
  2264                              <1> ;		    (Data section for 'VIDEO.INC')	
  2265                              <1> ;
  2266                              <1> ; ///////// VIDEO DATA ///////////////
  2267                              <1> 
  2268                              <1> video_params:
  2269                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2270                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2271                              <1> 	; VIDEO MODE 3
  2272 00006548 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2273 0000654F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2274 00006554 00000000            <1> 	db	0,0,0,0
  2275                              <1> 
  2276                              <1> ; /// End Of VIDEO DATA ///
  2262                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2263                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2264                              <1> ; Last Modification: 11/03/2015
  2265                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2266                              <1> ;
  2267                              <1> ; *****************************************************************************
  2268                              <1> 
  2269                              <1> ;----------------------------------------
  2270                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2271                              <1> ;	REFERENCED BY POST & BIOS	:
  2272                              <1> ;----------------------------------------
  2273                              <1> 
  2274 00006558 [BB650000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2275                              <1> 
  2276                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2277                              <1> ;----------------------------------------------------------------
  2278                              <1> ; DISK_BASE							:
  2279                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2280                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2281                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2282                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2283                              <1> ;----------------------------------------------------------------
  2284                              <1> 
  2285                              <1> ;DISK_BASE:	
  2286                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2287                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2288                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2289                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2290                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2291                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2292                              <1> ;	DB	01BH		; GAP LENGTH
  2293                              <1> ;	DB	0FFH		; DTL
  2294                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2295                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2296                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2297                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2298                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2299                              <1> 
  2300                              <1> ;----------------------------------------
  2301                              <1> ;	ROM BIOS DATA AREAS		:
  2302                              <1> ;----------------------------------------
  2303                              <1> 
  2304                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2305                              <1> 
  2306                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2307                              <1> 
  2308                              <1> ;----------------------------------------
  2309                              <1> ;	DISKETTE DATA AREAS		:
  2310                              <1> ;----------------------------------------
  2311                              <1> 
  2312                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2313                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2314                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2315                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2316                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2317                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2318                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2319                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2320                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2321                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2322                              <1> 
  2323                              <1> ;----------------------------------------
  2324                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2325                              <1> ;----------------------------------------
  2326                              <1> 
  2327                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2328                              <1> 
  2329                              <1> ;----------------------------------------
  2330                              <1> ;	TIMER DATA AREA 		:
  2331                              <1> ;----------------------------------------
  2332                              <1> 
  2333                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2334                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2335                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2336                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2337                              <1> 
  2338                              <1> ;----------------------------------------
  2339                              <1> ;	ADDITIONAL MEDIA DATA		:
  2340                              <1> ;----------------------------------------
  2341                              <1> 
  2342                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2343                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2344                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2345                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2346                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2347                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2348                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2349                              <1> 
  2350                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2351                              <1> 
  2352                              <1> ;--------------------------------------------------------
  2353                              <1> ;	DRIVE TYPE TABLE				:
  2354                              <1> ;--------------------------------------------------------
  2355                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2356                              <1> DR_TYPE:
  2357 0000655C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2358                              <1>                 ;DW      MD_TBL1
  2359 0000655D [7A650000]          <1> 		dd	MD_TBL1
  2360 00006561 82                  <1> 		DB	02+BIT7ON
  2361                              <1> 		;DW      MD_TBL2
  2362 00006562 [87650000]          <1>                 dd      MD_TBL2
  2363 00006566 02                  <1> DR_DEFAULT:	DB	02
  2364                              <1>                 ;DW      MD_TBL3
  2365 00006567 [94650000]          <1> 		dd      MD_TBL3
  2366 0000656B 03                  <1> 		DB	03
  2367                              <1>                 ;DW      MD_TBL4
  2368 0000656C [A1650000]          <1> 		dd      MD_TBL4
  2369 00006570 84                  <1> 		DB	04+BIT7ON
  2370                              <1>                 ;DW      MD_TBL5
  2371 00006571 [AE650000]          <1> 		dd      MD_TBL5
  2372 00006575 04                  <1> 		DB	04
  2373                              <1>                 ;DW      MD_TBL6
  2374 00006576 [BB650000]          <1> 		dd      MD_TBL6
  2375                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2376                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2377                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2378                              <1> ;--------------------------------------------------------
  2379                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2380                              <1> ;--------------------------------------------------------
  2381                              <1> ;--------------------------------------------------------
  2382                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2383                              <1> ;--------------------------------------------------------
  2384                              <1> MD_TBL1:        
  2385 0000657A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2386 0000657B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2387 0000657C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2388 0000657D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2389 0000657E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2390 0000657F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2391 00006580 FF                  <1> 	DB	0FFH		; DTL
  2392 00006581 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2393 00006582 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2394 00006583 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2395 00006584 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2396 00006585 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2397 00006586 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2398                              <1> ;--------------------------------------------------------
  2399                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2400                              <1> ;--------------------------------------------------------
  2401                              <1> MD_TBL2:        
  2402 00006587 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2403 00006588 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2404 00006589 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2405 0000658A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2406 0000658B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2407 0000658C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2408 0000658D FF                  <1> 	DB	0FFH		; DTL
  2409 0000658E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2410 0000658F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2411 00006590 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2412 00006591 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2413 00006592 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2414 00006593 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2415                              <1> ;--------------------------------------------------------
  2416                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2417                              <1> ;--------------------------------------------------------
  2418                              <1> MD_TBL3:
  2419 00006594 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2420 00006595 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2421 00006596 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2422 00006597 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2423 00006598 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2424 00006599 1B                  <1> 	DB	01BH		; GAP LENGTH
  2425 0000659A FF                  <1> 	DB	0FFH		; DTL
  2426 0000659B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2427 0000659C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2428 0000659D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2429 0000659E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2430 0000659F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2431 000065A0 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2432                              <1> ;--------------------------------------------------------
  2433                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2434                              <1> ;--------------------------------------------------------
  2435                              <1> MD_TBL4:
  2436 000065A1 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2437 000065A2 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2438 000065A3 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2439 000065A4 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2440 000065A5 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2441 000065A6 2A                  <1> 	DB	02AH		; GAP LENGTH
  2442 000065A7 FF                  <1> 	DB	0FFH		; DTL
  2443 000065A8 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2444 000065A9 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2445 000065AA 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2446 000065AB 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2447 000065AC 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2448 000065AD 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2449                              <1> ;--------------------------------------------------------
  2450                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2451                              <1> ;--------------------------------------------------------
  2452                              <1> MD_TBL5:
  2453 000065AE DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2454 000065AF 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2455 000065B0 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2456 000065B1 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2457 000065B2 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2458 000065B3 2A                  <1> 	DB	02AH		; GAP LENGTH
  2459 000065B4 FF                  <1> 	DB	0FFH		; DTL
  2460 000065B5 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2461 000065B6 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2462 000065B7 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2463 000065B8 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2464 000065B9 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2465 000065BA 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2466                              <1> ;--------------------------------------------------------
  2467                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2468                              <1> ;--------------------------------------------------------
  2469                              <1> MD_TBL6:
  2470 000065BB AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2471 000065BC 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2472 000065BD 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2473 000065BE 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2474 000065BF 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2475 000065C0 1B                  <1> 	DB	01BH		; GAP LENGTH
  2476 000065C1 FF                  <1> 	DB	0FFH		; DTL
  2477 000065C2 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2478 000065C3 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2479 000065C4 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2480 000065C5 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2481 000065C6 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2482 000065C7 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2483                              <1> 
  2484                              <1> 
  2485                              <1> ; << diskette.inc >>
  2486                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2487                              <1> ;
  2488                              <1> ;----------------------------------------
  2489                              <1> ;	ROM BIOS DATA AREAS		:
  2490                              <1> ;----------------------------------------
  2491                              <1> 
  2492                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2493                              <1> 
  2494                              <1> ;----------------------------------------
  2495                              <1> ;	FIXED DISK DATA AREAS		:
  2496                              <1> ;----------------------------------------
  2497                              <1> 
  2498                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2499                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2500                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2501                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2502                              <1> 
  2503                              <1> ;----------------------------------------
  2504                              <1> ;	ADDITIONAL MEDIA DATA		:
  2505                              <1> ;----------------------------------------
  2506                              <1> 
  2507                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2508                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2509                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2510                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2511                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2512                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2513                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2514                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2515                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2516                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2517                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2518                              <1> 
  2519                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2520                              <1> ;
  2521                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2522                              <1> 
  2523                              <1> ERR_TBL:
  2524 000065C8 E0                  <1> 	db	NO_ERR
  2525 000065C9 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2526 000065CD 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2527                              <1> 
  2528                              <1> ; 17/12/2014 (mov ax, [cfd])
  2529                              <1> ; 11/12/2014
  2530 000065D1 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2531                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2532 000065D2 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2533                              <1> 					; (initial value of 'pfd 
  2534                              <1> 					; must be different then 'cfd' value
  2535                              <1> 					; to force updating/initializing
  2536                              <1> 					; current drive parameters) 
  2537 000065D3 90                  <1> align 2
  2538                              <1> 
  2539 000065D4 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2540                              <1> 			      ; (170h)
  2541 000065D6 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2542                              <1> 
  2543                              <1> ; 05/01/2015 
  2544 000065D8 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2545                              <1> 
  2546                              <1> ; *****************************************************************************
  2263                                  ;;;
  2264                                  
  2265 000065D9 90                      Align 2
  2266                                  
  2267                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2268 000065DA 00                      boot_drv:    db 0 ; boot drive number (physical)
  2269                                  ; 24/11/2014
  2270 000065DB 00                      drv:	     db 0 
  2271 000065DC 00                      last_drv:    db 0 ; last hdd
  2272 000065DD 00                      hdc:         db 0  ; number of hard disk drives
  2273                                  		     ; (present/detected)
  2274                                  ;
  2275                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2276                                  ; Physical drive type & flags
  2277 000065DE 00                      fd0_type:    db 0  ; floppy drive type
  2278 000065DF 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2279                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2280                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2281                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2282                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2283 000065E0 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2284 000065E1 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2285 000065E2 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2286 000065E3 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2287                                  		     ; bit 0 - Fixed disk access subset supported
  2288                                  		     ; bit 1 - Drive locking and ejecting
  2289                                  		     ; bit 2 - Enhanced disk drive support
  2290                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2291                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2292                                  		     ; will interpret it as 'LBA ready'!)		
  2293                                  
  2294                                  ; 11/03/2015 - 10/07/2015
  2295 000065E4 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2295 000065ED 0000000000         
  2296 000065F2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2296 000065FB 0000000000         
  2297 00006600 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2297 00006609 0000000000         
  2298 0000660E 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2298 00006617 000000000000000000-
  2298 00006620 000000000000000000-
  2298 00006629 00                 
  2299 0000662A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2300 00006631 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2301                                  ;
  2302                                  
  2303                                  ; 27/08/2014
  2304                                  scr_row:
  2305 00006638 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2306                                  scr_col:
  2307 0000663C 00000000                	dd 0
  2308                                  
  2309                                  ;; 14/08/2015
  2310                                  ;;msgPM:
  2311                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2312                                  msgKVER:
  2313                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2314 00006640 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [03/03/2022]", 0	
  2314 00006649 582033383620763120-
  2314 00006652 2D204B65726E656C20-
  2314 0000665B 76302E322E302E3138-
  2314 00006664 205B30332F30332F32-
  2314 0000666D 3032325D00         
  2315                                  
  2316                                  Align 2
  2317                                  
  2318                                  ; 20/08/2014
  2319                                    ; /* This is the default interrupt "handler" :-) */ 
  2320                                    ; Linux v0.12 (head.s)
  2321                                  int_msg:
  2322 00006672 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2322 0000667B 6E7465727275707420-
  2322 00006684 212000             
  2323                                  
  2324 00006687 90                      Align 2  
  2325                                  
  2326                                  ; 21/08/2014
  2327                                  timer_msg:
  2328 00006688 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2328 00006691 542032306829202120-
  2328 0000669A 54696D657220496E74-
  2328 000066A3 657272757074203A20 
  2329                                  tcountstr:
  2330 000066AC 303030303020            	db "00000 "
  2331 000066B2 00                      	db 0
  2332                                  
  2333 000066B3 90                      Align 2
  2334                                  	; 21/08/2014
  2335                                  exc_msg:
  2336 000066B4 435055206578636570-     	db "CPU exception ! "
  2336 000066BD 74696F6E202120     
  2337                                  excnstr: 		; 25/08/2014
  2338 000066C4 3F3F68202045495020-     	db "??h", "  EIP : "
  2338 000066CD 3A20               
  2339                                  EIPstr: ; 29/08/2014
  2340 000066CF 00<rep Ch>              	times 12 db 0
  2341                                  rtc_msg:
  2342 000066DB 5265616C2054696D65-     	db "Real Time Clock - "
  2342 000066E4 20436C6F636B202D20 
  2343                                  datestr:
  2344 000066ED 30302F30302F303030-     	db "00/00/0000"
  2344 000066F6 30                 
  2345 000066F7 20                      	db " "
  2346                                  daystr:
  2347 000066F8 44415920                	db "DAY "
  2348                                  timestr:	
  2349 000066FC 30303A30303A3030                db "00:00:00"
  2350 00006704 20                      	db " "
  2351 00006705 00                      	db 0 
  2352                                  
  2353                                  daytmp:
  2354                                  	; 28/02/2015
  2355 00006706 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2355 0000670F 4F4E20545545205745-
  2355 00006718 442054485520465249-
  2355 00006721 2053415420         
  2356                                  
  2357 00006726 FF                      ptime_seconds: db 0FFh
  2358                                  
  2359                                  	; 23/02/2015
  2360                                  	; 25/08/2014
  2361                                  ;scounter:
  2362                                  ;	db 5
  2363                                  ;	db 19
  2364                                  
  2365                                  ;; 05/11/2014
  2366                                  ;msg_out_of_memory:
  2367                                  ;	db 	07h, 0Dh, 0Ah
  2368                                  ;	db      'Insufficient memory ! '
  2369                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2370                                  ; 	db	0Dh, 0Ah, 0
  2371                                  	;
  2372                                  setup_error_msg:
  2373 00006727 0D0A                    	db 0Dh, 0Ah
  2374 00006729 4469736B2053657475-     	db 'Disk Setup Error!' 
  2374 00006732 70204572726F7221   
  2375 0000673A 0D0A00                  	db 0Dh, 0Ah,0
  2376                                  
  2377                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2378                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2379                                  ;	  db 0 ; upper left row (for scroll)	
  2380                                  
  2381                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2382                                  ;	  db 24 ; lower right row (for scroll)
  2383                                  
  2384                                  
  2385                                  ; 06/11/2014 (Temporary Data)
  2386                                  ; Memory Information message
  2387                                  ; 14/08/2015
  2388                                  msg_memory_info:
  2389 0000673D 07                      	db	07h
  2390 0000673E 0D0A                    	db	0Dh, 0Ah
  2391                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2392 00006740 546F74616C206D656D-     	db	"Total memory : "
  2392 00006749 6F7279203A20       
  2393                                  mem_total_b_str: ; 10 digits
  2394 0000674F 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2394 00006758 302062797465730D0A 
  2395 00006761 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2395 0000676A 202020202020202020 
  2396                                  mem_total_p_str: ; 7 digits
  2397 00006773 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2397 0000677C 616765730D0A       
  2398 00006782 0D0A                    	db 	0Dh, 0Ah
  2399 00006784 46726565206D656D6F-     	db	"Free memory  : "
  2399 0000678D 727920203A20       
  2400                                  free_mem_b_str:  ; 10 digits
  2401 00006793 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2401 0000679C 3F2062797465730D0A 
  2402 000067A5 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2402 000067AE 202020202020202020 
  2403                                  free_mem_p_str:  ; 7 digits
  2404 000067B7 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2404 000067C0 616765730D0A       
  2405 000067C6 0D0A00                  	db	0Dh, 0Ah, 0
  2406                                  
  2407                                  dsk_ready_msg:
  2408 000067C9 0D0A                    	db 	0Dh, 0Ah
  2409                                  dsktype:
  2410 000067CB 6664                    	db	'fd'
  2411                                  dskx:
  2412 000067CD 30                      	db	'0'
  2413 000067CE 20                      	db	20h
  2414 000067CF 697320524541445920-     	db 	'is READY ...'
  2414 000067D8 2E2E2E             
  2415 000067DB 00                      	db 	0
  2416                                  nextline:
  2417 000067DC 0D0A00                  	db 	0Dh, 0Ah, 0
  2418                                  
  2419                                  ; KERNEL - SYSINIT Messages
  2420                                  ; 24/08/2015
  2421                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2422                                  ; 14/07/2013
  2423                                  ;kernel_init_err_msg:
  2424                                  ;	db 0Dh, 0Ah
  2425                                  ;	db 07h
  2426                                  ;	db 'Kernel initialization ERROR !'
  2427                                  ;	db 0Dh, 0Ah, 0 
  2428                                  ; 24/08/2015
  2429                                  ;;; (temporary kernel init message has been removed
  2430                                  ;;;  from 'sys_init' code)
  2431                                  ;kernel_init_ok_msg: 
  2432                                  ;	db 0Dh, 0Ah
  2433                                  ;	db 07h
  2434                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2435                                  ;	db 0Dh, 0Ah
  2436                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2437                                  ;	db 0Dh, 0Ah, 0
  2438                                  panic_msg:
  2439 000067DF 0D0A07                  	db 0Dh, 0Ah, 07h
  2440 000067E2 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2440 000067EB 726E656C2050616E69-
  2440 000067F4 632021             
  2441 000067F7 0D0A00                  	db 0Dh, 0Ah, 0
  2442                                  etc_init_err_msg:
  2443 000067FA 0D0A                    	db 0Dh, 0Ah
  2444 000067FC 07                      	db 07h
  2445 000067FD 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2445 00006806 74632F696E69742021-
  2445 0000680F 3F                 
  2446 00006810 0D0A00                  	db 0Dh, 0Ah, 0
  2447                                  
  2448                                  ; 10/05/2015
  2449                                  badsys_msg:
  2450 00006813 0D0A                    	db 0Dh, 0Ah
  2451 00006815 07                      	db 07h
  2452 00006816 496E76616C69642053-     	db 'Invalid System Call !'
  2452 0000681F 797374656D2043616C-
  2452 00006828 6C2021             
  2453 0000682B 0D0A                    	db 0Dh, 0Ah
  2454 0000682D 4541583A20              	db 'EAX: '
  2455                                  bsys_msg_eax:
  2456 00006832 303030303030303068      	db '00000000h'
  2457 0000683B 0D0A                    	db 0Dh, 0Ah
  2458 0000683D 4549503A20              	db 'EIP: '
  2459                                  bsys_msg_eip:
  2460 00006842 303030303030303068      	db '00000000h' 
  2461 0000684B 0D0A00                  	db 0Dh, 0Ah, 0
  2462                                  
  2463                                  BSYS_M_SIZE equ $ - badsys_msg
  2464                                  
  2465                                  
  2466                                  align 2
  2467                                  
  2468                                  ; EPOCH Variables
  2469                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2470                                  ; 09/04/2013 epoch variables
  2471                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2472                                  ;
  2473 0000684E B207                    year: 	dw 1970
  2474 00006850 0100                    month: 	dw 1
  2475 00006852 0100                    day: 	dw 1
  2476 00006854 0000                    hour: 	dw 0
  2477 00006856 0000                    minute: dw 0
  2478 00006858 0000                    second: dw 0
  2479                                  
  2480                                  DMonth:
  2481 0000685A 0000                    	dw 0
  2482 0000685C 1F00                    	dw 31
  2483 0000685E 3B00                    	dw 59
  2484 00006860 5A00                    	dw 90
  2485 00006862 7800                    	dw 120
  2486 00006864 9700                    	dw 151
  2487 00006866 B500                    	dw 181
  2488 00006868 D400                    	dw 212
  2489 0000686A F300                    	dw 243
  2490 0000686C 1101                    	dw 273
  2491 0000686E 3001                    	dw 304
  2492 00006870 4E01                    	dw 334
  2493                                  
  2494                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2495 00006872 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2496                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2497 00006874 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2498                                  		   ;   between 16 MB and 4 GB.
  2499                                  
  2500 00006876 90<rep Ah>              align 16
  2501                                  
  2502                                  bss_start:
  2503                                  
  2504                                  ABSOLUTE bss_start
  2505                                  
  2506                                  	; 11/03/2015
  2507                                  	; Interrupt Descriptor Table (20/08/2014)
  2508                                  idt:
  2509 00006880 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2510                                  idt_end:
  2511                                  
  2512                                  ;alignb 4
  2513                                  
  2514                                  task_state_segment:
  2515                                  	; 24/03/2015
  2516 00006A80 ????                    tss.link:   resw 1
  2517 00006A82 ????                    	    resw 1
  2518                                  ; tss offset 4	
  2519 00006A84 ????????                tss.esp0:   resd 1
  2520 00006A88 ????                    tss.ss0:    resw 1
  2521 00006A8A ????                    	    resw 1	
  2522 00006A8C ????????                tss.esp1:   resd 1
  2523 00006A90 ????                    tss.ss1:    resw 1
  2524 00006A92 ????                    	    resw 1 	
  2525 00006A94 ????????                tss.esp2:   resd 1
  2526 00006A98 ????                    tss.ss2:    resw 1
  2527 00006A9A ????                    	    resw 1
  2528                                  ; tss offset 28
  2529 00006A9C ????????                tss.CR3:    resd 1
  2530 00006AA0 ????????                tss.eip:    resd 1
  2531 00006AA4 ????????                tss.eflags: resd 1
  2532                                  ; tss offset 40
  2533 00006AA8 ????????                tss.eax:    resd 1		 		
  2534 00006AAC ????????                tss.ecx:    resd 1
  2535 00006AB0 ????????                tss.edx:    resd 1
  2536 00006AB4 ????????                tss.ebx:    resd 1
  2537 00006AB8 ????????                tss.esp:    resd 1
  2538 00006ABC ????????                tss.ebp:    resd 1
  2539 00006AC0 ????????                tss.esi:    resd 1
  2540 00006AC4 ????????                tss.edi:    resd 1
  2541                                  ; tss offset 72
  2542 00006AC8 ????                    tss.ES:     resw 1
  2543 00006ACA ????                    	    resw 1	
  2544 00006ACC ????                    tss.CS:	    resw 1
  2545 00006ACE ????                    	    resw 1
  2546 00006AD0 ????                    tss.SS:	    resw 1
  2547 00006AD2 ????                    	    resw 1
  2548 00006AD4 ????                    tss.DS:	    resw 1
  2549 00006AD6 ????                    	    resw 1
  2550 00006AD8 ????                    tss.FS:	    resw 1
  2551 00006ADA ????                    	    resw 1
  2552 00006ADC ????                    tss.GS:	    resw 1
  2553 00006ADE ????                    	    resw 1		
  2554 00006AE0 ????                    tss.LDTR:   resw 1
  2555 00006AE2 ????                    	    resw 1
  2556                                  ; tss offset 100		
  2557 00006AE4 ????                    	    resw 1		
  2558 00006AE6 ????                    tss.IOPB:   resw 1
  2559                                  ; tss offset 104 
  2560                                  tss_end:
  2561                                  
  2562 00006AE8 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2563                                  		    ; (Physical address = Virtual address)	 	
  2564 00006AEC ????????                memory_size: resd 1 ; memory size in pages
  2565 00006AF0 ????????                free_pages:  resd 1 ; number of free pages		
  2566 00006AF4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2567                                  		    ; first free page search
  2568 00006AF8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2569                                  		    ; next free page search will be
  2570                                  		    ; stopped after it. (end of M.A.T.)
  2571 00006AFC ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2572                                  		    ; first free page search
  2573                                  		    ; will be started on it. (for user)
  2574 00006B00 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2575                                  
  2576                                  ;;;
  2577                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2578                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2579 00006B04 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2580                                  		    ; NOTE: active page only
  2581 00006B06 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2582                                  active_page: 
  2583 00006B16 ??                      ptty: 	     resb 1 ; current tty
  2584                                  ; 01/07/2015
  2585 00006B17 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2586                                  ; 26/10/2015
  2587                                  ; 07/09/2014
  2588 00006B18 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2589                                  
  2590                                  ; 21/08/2014
  2591 00006B2C ????????                tcount:	     resd 1
  2592                                  
  2593                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2594 00006B30 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2595                                  
  2596                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2597                                  ; (open mode locks for pseudo TTYs)
  2598                                  ; [ major tty locks (return error in any conflicts) ]
  2599 00006B34 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2600                                  
  2601                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2602                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2603 00006B48 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2604                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2605                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2606                                  ;; 0 means serial port is not available 
  2607                                  ;;comprm: ; 25/06/2014
  2608 00006B52 ??                      com1p:       resb 1 ;;0E3h
  2609 00006B53 ??                      com2p:       resb 1 ;;0E3h
  2610                                  
  2611                                  ; 17/11/2015
  2612                                  ; request for response (from the terminal)	
  2613 00006B54 ????                    req_resp:     resw 1 			
  2614                                  ; 07/11/2015
  2615 00006B56 ??                      ccomport:    resb 1 ; current COM (serial) port
  2616                                  		    ; (0= COM1, 1= COM2)
  2617                                  ; 09/11/2015
  2618 00006B57 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2619                                  ; 07/11/2015
  2620 00006B58 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2621 00006B5A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2622                                  
  2623                                  ; 23/10/2015
  2624                                  ; SERIAL PORTS - COMMUNICATION MODES
  2625                                  ; (Retro UNIX 386 v1 feature only!)
  2626                                  ; 0 - command mode (default/initial mode)
  2627                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2628                                  ;;; communication modes for future versions:  
  2629                                  ; // 2 - keyboard mode (ascii+scancode input)
  2630                                  ; // 3 - mouse mode
  2631                                  ; // 4 - device control (output) mode
  2632                                  ; VALID COMMANDS for current version:
  2633                                  ; 	'LOGIN'
  2634                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2635                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2636                                  ;  Login response: db 0FFh, 'login', 0
  2637                                  ;	 ("login request accepted, wait for login prompt") 
  2638                                  ; When a login requests is received and acknowledged (by
  2639                                  ; serial port interrupt handler (communication procedure),
  2640                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2641                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2642                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2643                                  ; 
  2644                                  ; 'sys connect' system call is used to change communication mode
  2645                                  ; except 'LOGIN' command which is used to start terminal mode
  2646                                  ; by using (COM port) terminal.
  2647                                  
  2648                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2649                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2650                                  ;com1mode:    resb 1 ; communication mode for COM1
  2651                                  ;com1com:     resb 1 ; communication command for COM1
  2652                                  ;com2mode:    resb 1 ; communication mode for COM1
  2653                                  ;com2com      resb 1 ; communication command for COM1
  2654                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2655                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2656                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2657                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2658                                  
  2659                                  ; 22/08/2014 (RTC)
  2660                                  ; (Packed BCD)
  2661 00006B5C ??                      time_seconds: resb 1
  2662 00006B5D ??                      time_minutes: resb 1
  2663 00006B5E ??                      time_hours:   resb 1
  2664 00006B5F ??                      date_wday:    resb 1
  2665 00006B60 ??                      date_day:     resb 1
  2666 00006B61 ??                      date_month:   resb 1			
  2667 00006B62 ??                      date_year:    resb 1
  2668 00006B63 ??                      date_century: resb 1
  2669                                  
  2670                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2671                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2672                              <1> ; Last Modification: 10/07/2015
  2673                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2674                              <1> ;
  2675                              <1> ; *****************************************************************************
  2676                              <1> 
  2677                              <1> alignb 2
  2678                              <1> 
  2679                              <1> ;----------------------------------------
  2680                              <1> ;	TIMER DATA AREA 		:
  2681                              <1> ;----------------------------------------
  2682                              <1> 
  2683                              <1> TIMER_LH:	; 16/02/205
  2684 00006B64 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2685 00006B66 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2686 00006B68 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2687                              <1> 
  2688                              <1> ;----------------------------------------
  2689                              <1> ;	DISKETTE DATA AREAS		:
  2690                              <1> ;----------------------------------------
  2691                              <1> 
  2692 00006B69 ??                  <1> SEEK_STATUS:	resb	1
  2693 00006B6A ??                  <1> MOTOR_STATUS:	resb	1
  2694 00006B6B ??                  <1> MOTOR_COUNT:	resb	1
  2695 00006B6C ??                  <1> DSKETTE_STATUS:	resb	1
  2696 00006B6D ??????????????      <1> NEC_STATUS:	resb	7
  2697                              <1> 
  2698                              <1> ;----------------------------------------
  2699                              <1> ;	ADDITIONAL MEDIA DATA		:
  2700                              <1> ;----------------------------------------
  2701                              <1> 
  2702 00006B74 ??                  <1> LASTRATE:	resb 	1
  2703 00006B75 ??                  <1> HF_STATUS:	resb 	1
  2704 00006B76 ??                  <1> HF_ERROR:	resb 	1
  2705 00006B77 ??                  <1> HF_INT_FLAG:	resb 	1
  2706 00006B78 ??                  <1> HF_CNTRL:	resb 	1
  2707 00006B79 ????????            <1> DSK_STATE:	resb 	4
  2708 00006B7D ????                <1> DSK_TRK:	resb 	2
  2709                              <1> 
  2710                              <1> ;----------------------------------------
  2711                              <1> ;	FIXED DISK DATA AREAS		:
  2712                              <1> ;----------------------------------------
  2713                              <1> 
  2714 00006B7F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2715 00006B80 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2716 00006B81 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2717                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2718                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2719                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2720                              <1> 
  2721 00006B82 ????                <1> alignb 4
  2722                              <1> 
  2723                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2724                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2725                              <1> HF_TBL_VEC: ; 22/12/2014	
  2726 00006B84 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2727 00006B88 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2728 00006B8C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2729 00006B90 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2730                              <1> 
  2731                              <1> ; 03/01/2015
  2732 00006B94 ??                  <1> LBAMode:     	resb	1
  2733                              <1> 
  2734                              <1> ; *****************************************************************************
  2671                                  
  2672                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2673                                  
  2674                                  ;alignb 2
  2675                                  
  2676                                  ; 27/02/2022
  2677                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2678                                  
  2679                                  ; 23/02/2022
  2680                                  ;; Memory (swap) Data (11/03/2015)
  2681                                  ; 09/03/2015
  2682                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2683                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2684                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2685                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2686                                  ;swpd_next:  resd 1 ; next free page block
  2687                                  ;swpd_last:  resd 1 ; last swap page block	
  2688                                  
  2689 00006B95 ??????                  alignb 4
  2690                                  
  2691                                  ; 10/07/2015
  2692                                  ; 28/08/2014
  2693 00006B98 ????????                error_code:	resd 1
  2694                                  ; 29/08/2014
  2695 00006B9C ????????                FaultOffset: 	resd 1
  2696                                  ; 21/09/2015
  2697 00006BA0 ????????                PF_Count:	resd 1	; total page fault count
  2698                                  		       	; (for debugging - page fault analyze)
  2699                                  		 	; 'page _fault_handler' (memory.inc)
  2700                                  			; 'sysgeterr' (u9.s)
  2701                                  ; 23/02/2022
  2702 00006BA4 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2703                                  			;  for a system call in next retro unix 386 version)
  2704                                  			; -2 ticks per second-
  2705                                  ;; 21/08/2015
  2706                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2707                                  
  2708                                  ; 27/02/2022
  2709                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2710                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYSX.INC (ux.s)
  2711                              <1> ; Last Modification: 26/02/2022
  2712                              <1> ;
  2713                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2714                              <1> ; (Modified from 
  2715                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2716                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2717                              <1> ; ----------------------------------------------------------------------------
  2718                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2719                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2720                              <1> ; <Bell Laboratories (17/3/1972)>
  2721                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2722                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2723                              <1> ; ****************************************************************************
  2724                              <1> ; 13/11/2015
  2725                              <1> 
  2726                              <1> alignb 2
  2727                              <1> 
  2728                              <1> inode:
  2729                              <1> 	; 11/03/2013. 
  2730                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2731                              <1> 	;i.
  2732                              <1> 
  2733 00006BA8 ????                <1> 	i.flgs:	 resw 1
  2734 00006BAA ??                  <1> 	i.nlks:	 resb 1
  2735 00006BAB ??                  <1> 	i.uid:	 resb 1
  2736 00006BAC ????                <1>         i.size:  resw 1 ; size
  2737 00006BAE <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2738 00006BBE ????????            <1> 	i.ctim:	 resd 1
  2739 00006BC2 ????????            <1> 	i.mtim:	 resd 1
  2740 00006BC6 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2741                              <1> 
  2742                              <1> I_SIZE	equ $ - inode 
  2743                              <1> 
  2744                              <1> process:
  2745                              <1> 	; 26/02/2022
  2746                              <1> 	; 04/02/2022
  2747                              <1> 	; 06/05/2015
  2748                              <1> 	; 11/03/2013 - 05/02/2014
  2749                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2750                              <1> 	;p.
  2751                              <1> 	
  2752 00006BC8 <res 20h>           <1>         p.pid:   resw nproc
  2753 00006BE8 <res 20h>           <1>         p.ppid:  resw nproc
  2754                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2755 00006C08 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2756                              <1> 	; 26/02/2022 (p.waitc is not used)
  2757                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2758 00006C18 <res 10h>           <1> 	p.link:	 resb nproc
  2759 00006C28 <res 10h>           <1> 	p.stat:	 resb nproc
  2760                              <1> 
  2761                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2762 00006C38 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2763                              <1> 			    ; 'user' structure	
  2764                              <1> 
  2765                              <1> 
  2766                              <1> P_SIZE	equ $ - process
  2767                              <1> 
  2768                              <1> 
  2769                              <1> ; fsp table (original UNIX v1)
  2770                              <1> ;
  2771                              <1> ;Entry
  2772                              <1> ;          15                                      0
  2773                              <1> ;  1     |---|---------------------------------------|
  2774                              <1> ;        |r/w|       i-number of open file           |
  2775                              <1> ;        |---|---------------------------------------| 
  2776                              <1> ;        |               device number               |
  2777                              <1> ;        |-------------------------------------------|
  2778                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2779                              <1> ;        |-------------------------------------------| 
  2780                              <1> ;        |  flag that says    | number of processes  |
  2781                              <1> ;        |   file deleted     | that have file open  |
  2782                              <1> ;        |-------------------------------------------| 
  2783                              <1> ;  2     |                                           |
  2784                              <1> ;        |-------------------------------------------| 
  2785                              <1> ;        |                                           |
  2786                              <1> ;        |-------------------------------------------|
  2787                              <1> ;        |                                           |
  2788                              <1> ;        |-------------------------------------------|
  2789                              <1> ;        |                                           |
  2790                              <1> ;        |-------------------------------------------| 
  2791                              <1> ;  3     |                                           | 
  2792                              <1> ;        |                                           |  
  2793                              <1> ;
  2794                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2795                              <1> 
  2796                              <1> 
  2797                              <1> ; 15/04/2015
  2798 00006C78 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2799 00006E6C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2800 00006E8C ????                <1> ii:	 resw 1
  2801 00006E8E ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2802 00006E90 ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2803                              <1> ; 18/05/2015
  2804                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2805                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2806                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2807                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2808                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2809                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2810                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2811                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2812                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2813                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2814                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2815 00006E92 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2816                              <1> 	        ; as above, for physical drives numbers in following table
  2817 00006E93 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2818                              <1> ; 15/04/2015
  2819 00006E94 ??                  <1> active:	 resb 1 
  2820 00006E95 ??                  <1> 	 resb 1 ; 09/06/2015
  2821 00006E96 ????                <1> mnti:	 resw 1
  2822 00006E98 ????                <1> mpid:	 resw 1
  2823 00006E9A ????                <1> rootdir: resw 1
  2824                              <1> ; 14/02/2014
  2825                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2826                              <1> ;		      Single level run queue
  2827                              <1> ;		      (in order to solve sleep/wakeup lock)
  2828 00006E9C ????                <1> runq:	 resw 1
  2829 00006E9E ??                  <1> imod:	 resb 1
  2830 00006E9F ??                  <1> smod:	 resb 1
  2831 00006EA0 ??                  <1> mmod:	 resb 1
  2832 00006EA1 ??                  <1> sysflg:	 resb 1
  2833                              <1> 
  2834 00006EA2 ????                <1> alignb 4
  2835                              <1> 
  2836                              <1> user:
  2837                              <1> 	; 18/10/2015
  2838                              <1> 	; 12/10/2015
  2839                              <1> 	; 21/09/2015
  2840                              <1> 	; 24/07/2015
  2841                              <1> 	; 16/06/2015
  2842                              <1> 	; 09/06/2015
  2843                              <1> 	; 11/05/2015
  2844                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2845                              <1> 	; 10/10/2013
  2846                              <1> 	; 11/03/2013. 
  2847                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2848                              <1> 	;u.
  2849                              <1> 
  2850 00006EA4 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2851 00006EA8 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2852 00006EAC ????????            <1> 	u.r0:	  resd 1 ; eax
  2853 00006EB0 ????                <1> 	u.cdir:	  resw 1
  2854 00006EB2 <res Ah>            <1> 	u.fp:	  resb 10
  2855 00006EBC ????????            <1> 	u.fofp:	  resd 1
  2856 00006EC0 ????????            <1> 	u.dirp:	  resd 1
  2857 00006EC4 ????????            <1> 	u.namep:  resd 1
  2858 00006EC8 ????????            <1> 	u.off:	  resd 1
  2859 00006ECC ????????            <1> 	u.base:	  resd 1
  2860 00006ED0 ????????            <1> 	u.count:  resd 1
  2861 00006ED4 ????????            <1> 	u.nread:  resd 1
  2862 00006ED8 ????????            <1> 	u.break:  resd 1 ; break
  2863 00006EDC ????                <1> 	u.ttyp:	  resw 1 
  2864 00006EDE <res Ah>            <1> 	u.dirbuf: resb 10
  2865                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2866 00006EE8 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2867 00006EE9 ??                  <1> 	u.pri:	  resb 1 ; 
  2868 00006EEA ????                <1> 	u.intr:	  resw 1
  2869 00006EEC ????                <1> 	u.quit:	  resw 1
  2870                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2871 00006EEE ????                <1> 	u.ilgins: resw 1
  2872 00006EF0 ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2873 00006EF2 ??                  <1> 	u.uid:	  resb 1 ; uid
  2874 00006EF3 ??                  <1> 	u.ruid:	  resb 1
  2875 00006EF4 ??                  <1> 	u.bsys:	  resb 1
  2876 00006EF5 ??                  <1> 	u.uno:	  resb 1
  2877 00006EF6 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2878                              <1> 	; tty number (rtty, rcvt, wtty)
  2879 00006EFA ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2880                              <1> 	; last error number
  2881 00006EFB ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2882                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2883 00006EFF ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2884 00006F03 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2885 00006F07 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2886 00006F0B ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2887                              <1> 	;u.pncount: resw 1 
  2888                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2889                              <1> 	;u.pnbase:  resd 1 
  2890                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2891                              <1> 			 ; 09/06/2015
  2892 00006F0D ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2893 00006F0E ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2894                              <1> 			 ; 24/07/2015 - 24/06/2015
  2895                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2896                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2897                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2898                              <1>  			 ; 24/06/2015	  	
  2899                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2900                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2901                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2902 00006F0F ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2903                              <1> 
  2904 00006F13 ??                  <1> alignb 4
  2905                              <1> 
  2906                              <1> U_SIZE	equ $ - user
  2907                              <1> 
  2908                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2909 00006F14 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2910 00006F18 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2911 00006F1C ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2912 00006F20 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2913 00006F22 ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2914 00006F24 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2915                              <1> 
  2916                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2917                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2918 00006F28 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2919 00006F29 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2920 00006F2A ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2921 00006F2B ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2922                              <1> 
  2923                              <1> ;alignb 4
  2924                              <1> 
  2925                              <1> ; 22/08/2015
  2926 00006F2C <res C30h>          <1> buffer: resb nbuf * 520
  2927                              <1> 
  2928 00007B5C ????????????????    <1> sb0:	resd 2
  2929                              <1> ;s:
  2930                              <1> ; (root disk) super block buffer
  2931                              <1> systm:
  2932                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2933                              <1> 	; 11/03/2013. 
  2934                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2935                              <1> 	;s.
  2936                              <1> 
  2937 00007B64 ????                <1> 	resw 1
  2938 00007B66 <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2939 00007CCE ????                <1> 	resw 1
  2940 00007CD0 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2941                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2942 00007CF0 ????????            <1> 	s.time:	 resd 1
  2943 00007CF4 ????????            <1> 	s.syst:	 resd 1
  2944 00007CF8 ????????            <1>         s.wait_: resd 1 ; wait
  2945 00007CFC ????????            <1> 	s.idlet: resd 1
  2946 00007D00 ????????            <1> 	s.chrgt: resd 1
  2947 00007D04 ????                <1> 	s.drerr: resw 1
  2948                              <1> 
  2949                              <1> S_SIZE	equ $ - systm
  2950                              <1> 
  2951 00007D06 <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2952                              <1> 
  2953 00007D64 ????????????????    <1> sb1:	resd 2
  2954                              <1> ; (mounted disk) super block buffer
  2955                              <1> mount:	
  2956 00007D6C <res 200h>          <1> 	resb 512  ; 03/06/2015
  2957                              <1> 
  2958                              <1> ;/ ux -- unix
  2959                              <1> ;
  2960                              <1> ;systm:
  2961                              <1> ;
  2962                              <1> ;	.=.+2
  2963                              <1> ;	.=.+128.
  2964                              <1> ;	.=.+2
  2965                              <1> ;	.=.+64.
  2966                              <1> ;	s.time: .=.+4
  2967                              <1> ;	s.syst: .=.+4
  2968                              <1> ;	s.wait: .=.+4
  2969                              <1> ;	s.idlet:.=.+4
  2970                              <1> ;	s.chrgt:.=.+4
  2971                              <1> ;	s.drerr:.=.+2
  2972                              <1> ;inode:
  2973                              <1> ;	i.flgs: .=.+2
  2974                              <1> ;	i.nlks: .=.+1
  2975                              <1> ;	i.uid:  .=.+1
  2976                              <1> ;	i.size: .=.+2
  2977                              <1> ;	i.dskp: .=.+16.
  2978                              <1> ;	i.ctim: .=.+4
  2979                              <1> ;	i.mtim: .=.+4
  2980                              <1> ;	. = inode+32.
  2981                              <1> ;mount:	.=.+1024.
  2982                              <1> ;proc:
  2983                              <1> ;	p.pid:  .=.+[2*nproc]
  2984                              <1> ;	p.dska: .=.+[2*nproc]
  2985                              <1> ;	p.ppid: .=.+[2*nproc]
  2986                              <1> ;	p.break:.=.+[2*nproc]
  2987                              <1> ;	p.link: .=.+nproc
  2988                              <1> ;	p.stat: .=.+nproc
  2989                              <1> ;tty:
  2990                              <1> ;	. = .+[ntty*8.]
  2991                              <1> ;fsp:	.=.+[nfiles*8.]
  2992                              <1> ;bufp:	.=.+[nbuf*2]+6
  2993                              <1> ;sb0:	.=.+8
  2994                              <1> ;sb1:	.=.+8
  2995                              <1> ;swp:	.=.+8
  2996                              <1> ;ii:	.=.+2
  2997                              <1> ;idev:	.=.+2
  2998                              <1> ;cdev:	.=.+2
  2999                              <1> ;deverr: .=.+12.
  3000                              <1> ;active: .=.+2
  3001                              <1> ;rfap:	.=.+2
  3002                              <1> ;rkap:	.=.+2
  3003                              <1> ;tcap:	.=.+2
  3004                              <1> ;tcstate:.=.+2
  3005                              <1> ;tcerrc: .=.+2
  3006                              <1> ;mnti:	.=.+2
  3007                              <1> ;mntd:	.=.+2
  3008                              <1> ;mpid:	.=.+2
  3009                              <1> ;clockp: .=.+2
  3010                              <1> ;rootdir:.=.+2
  3011                              <1> ;toutt:	.=.+16.
  3012                              <1> ;touts: .=.+32.
  3013                              <1> ;runq:	.=.+6
  3014                              <1> ;
  3015                              <1> ;wlist:	.=.+40.
  3016                              <1> ;cc:	.=.+30.
  3017                              <1> ;cf:	.=.+31.
  3018                              <1> ;cl:	.=.+31.
  3019                              <1> ;clist:	.=.+510.
  3020                              <1> ;imod:	.=.+1
  3021                              <1> ;smod:	.=.+1
  3022                              <1> ;mmod:	.=.+1
  3023                              <1> ;uquant: .=.+1
  3024                              <1> ;sysflg: .=.+1
  3025                              <1> ;pptiflg:.=.+1
  3026                              <1> ;ttyoch: .=.+1
  3027                              <1> ; .even
  3028                              <1> ; .=.+100.; sstack:
  3029                              <1> ;buffer: .=.+[ntty*140.]
  3030                              <1> ;	.=.+[nbuf*520.]
  3031                              <1> ;
  3032                              <1> ; . = core-64.
  3033                              <1> ;user:
  3034                              <1> ;	u.sp:    .=.+2
  3035                              <1> ;	u.usp:   .=.+2
  3036                              <1> ;	u.r0:    .=.+2
  3037                              <1> ;	u.cdir:  .=.+2
  3038                              <1> ;	u.fp:    .=.+10.
  3039                              <1> ;	u.fofp:  .=.+2
  3040                              <1> ;	u.dirp:  .=.+2
  3041                              <1> ;	u.namep: .=.+2
  3042                              <1> ;	u.off:   .=.+2
  3043                              <1> ;	u.base:  .=.+2
  3044                              <1> ;	u.count: .=.+2
  3045                              <1> ;	u.nread: .=.+2
  3046                              <1> ;	u.break: .=.+2
  3047                              <1> ;	u.ttyp:  .=.+2
  3048                              <1> ;	u.dirbuf:.=.+10.
  3049                              <1> ;	u.pri:   .=.+2
  3050                              <1> ;	u.intr:  .=.+2
  3051                              <1> ;	u.quit:  .=.+2
  3052                              <1> ;	u.emt:   .=.+2
  3053                              <1> ;	u.ilgins:.=.+2
  3054                              <1> ;	u.cdev:  .=.+2
  3055                              <1> ;	u.uid:   .=.+1
  3056                              <1> ;	u.ruid:  .=.+1
  3057                              <1> ;	u.bsys:  .=.+1
  3058                              <1> ;	u.uno:   .=.+1
  3059                              <1> ;. = core
  2710                                  
  2711                                  bss_end:
  2712                                  
  2713                                  ; 27/02/2022
  2714                                  BSS_SIZE equ bss_end - bss_start
  2715                                  
  2716                                  ; 27/12/2013
  2717                                  _end:  ; end of kernel code (and read only data, just before bss)
