     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: 26/02/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) - 16/02/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[3A66]              	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[D268]              	mov	[mem_1m_1k], cx
   172 00000017 8916[D468]              	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[3D66]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   234 0000008A 8816[3C66]          <1>         mov     [last_drv], dl  ; last hard disk number
   235 0000008E BB[C065]            <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[3E66]            <1> 	mov	si, fd0_type
   253                              <1> L3:
   254                              <1> 	; 14/01/2015
   255 0000009F 8816[3B66]          <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[3E66]          <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[3D66]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[3B66]          <1>         mov     [drv], dl
   289 000000CB 8816[3C66]          <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[3D66]          <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[3B66]          <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[3B66]          <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[3B66]          <1> 	inc	byte [drv]
   351 0000013C BB[C065]            <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[3D66]            <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[3B66]          <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[3B66]          <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[4066]          <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[3E66]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   413 00000193 81C3[8A66]          <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[8A66]          <1> 	sub	bx, drv.status
   422 000001A5 C1E302              <1> 	shl	bx, 2
   423 000001A8 81C3[6E66]          <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[4066]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   528 00000233 808F[8C66]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[8C66]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[3C66]          <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[3B66]          <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[8A66]          <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[8A66]          <1> 	sub	bx, drv.status
   728 00000289 D0E3                <1> 	shl	bl, 1
   729 0000028B 81C3[4466]          <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[4466]          <1> 	sub	bx, drv.cylinders
   734 00000297 81C3[5266]          <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[5266]          <1>         sub     bx, drv.heads
   740 000002A6 81C3[6066]          <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[6066]          <1>         sub     bx, drv.spt
   745 000002B5 D1E3                <1> 	shl	bx, 1
   746 000002B7 81C3[6E66]          <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[6063]                  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 00000324 B9BA050000              	mov  ecx, (bss_end - bss_start)/4
   299                                  	;shr  ecx, 2 ; bss section is already aligned for double words
   300 00000329 BF[E0680000]            	mov  edi, bss_start	
   301 0000032E F3AB                    	rep  stosd  		
   302                                  
   303                                  memory_init:
   304                                  	; Initialize memory allocation table and page tables
   305                                  	; 16/11/2014
   306                                  	; 15/11/2014
   307                                  	; 07/11/2014
   308                                  	; 06/11/2014
   309                                  	; 05/11/2014
   310                                  	; 04/11/2014
   311                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   312                                  	;
   313                                  ;	xor	eax, eax
   314                                  ;	xor 	ecx, ecx
   315 00000330 B108                    	mov	cl, 8
   316 00000332 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   317 00000337 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   318                                  				   ; for the first 1 MB memory
   319                                  	;
   320 00000339 668B0D[D2680000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   321                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   322 00000340 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   323 00000344 890D[506B0000]          	mov	[free_pages], ecx
   324 0000034A 668B15[D4680000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   325                                  				   ; between 16 MB and 4 GB.	
   326 00000351 6609D2                  	or	dx, dx
   327 00000354 7413                    	jz	short mi_0
   328                                  	;
   329 00000356 6689D0                  	mov	ax, dx
   330 00000359 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   331 0000035C 0105[506B0000]          	add	[free_pages], eax
   332 00000362 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   333 00000367 EB07                    	jmp	short mi_1
   334                                  mi_0:
   335 00000369 6689C8                  	mov	ax, cx
   336 0000036C 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   337                                  mi_1:
   338 00000370 A3[4C6B0000]            	mov	[memory_size], eax ; Total available memory in pages
   339                                  				   ; 1 alloc. tbl. bit = 1 memory page
   340                                  				   ; 32 allocation bits = 32 mem. pages   
   341                                  	;
   342 00000375 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   343 0000037A C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   344                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   345                                  				   ;  --> x M.A.T. pages, if y = 0
   346 0000037D 66A3[606B0000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   347 00000383 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   348                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   349 00000386 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   350                                  	; Set/Calculate Kernel's Page Directory Address
   351 00000388 81C300001000            	add	ebx, MEM_ALLOC_TBL
   352 0000038E 891D[486B0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   353                                  				   ; just after the last M.A.T. page
   354                                  	;
   355 00000394 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   356 00000397 A3[586B0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   357                                  	;			   ; (allocation status search must be 
   358                                  				   ; stopped after here)	
   359 0000039C 31C0                    	xor	eax, eax
   360 0000039E 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   361 0000039F 6651                    	push	cx
   362 000003A1 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   363                                  				   ; count of 32 allocation bits
   364 000003A4 F3AB                    	rep	stosd
   365 000003A6 6659                    	pop	cx
   366 000003A8 40                      	inc	eax		   ; 0	
   367 000003A9 80E11F                  	and	cl, 31		   ; remain bits
   368 000003AC 7412                    	jz	short mi_4
   369 000003AE 8907                    	mov	[edi], eax	   ; reset	
   370                                  mi_2:
   371 000003B0 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   372 000003B3 FEC9                    	dec	cl
   373 000003B5 7404                    	jz	short mi_3
   374 000003B7 FEC0                    	inc	al
   375 000003B9 EBF5                    	jmp	short mi_2
   376                                  mi_3:
   377 000003BB 28C0                    	sub	al, al	   	   ; 0
   378 000003BD 83C704                  	add	edi, 4		   ; 15/11/2014
   379                                  mi_4:
   380 000003C0 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   381 000003C3 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   382                                  	;	
   383 000003C5 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   384                                  	;	
   385 000003CA 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   386 000003CC 7406                    	jz	short mi_5	  ; jump if EDI points to 
   387                                  				  ;         end of first 16 MB	
   388 000003CE D1E9                    	shr	ecx, 1		  ; convert to dword count
   389 000003D0 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   390 000003D2 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   391                                  				  ; (memory hole under 16 MB)
   392                                  mi_5:
   393 000003D4 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   394 000003D7 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   395 000003D9 9C                      	pushf			  ; 16/11/2014		
   396 000003DA 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   397 000003DB F3AB                    	rep	stosd
   398 000003DD 40                      	inc	eax		  ; 0
   399 000003DE 9D                      	popf			  ; 16/11/2014
   400 000003DF 7305                    	jnc	short mi_6
   401 000003E1 6648                    	dec	ax		  ; eax = 0000FFFFh
   402 000003E3 AB                      	stosd
   403 000003E4 6640                    	inc	ax		  ; 0		
   404                                  mi_6:
   405 000003E6 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   406 000003E8 730A                    	jnb	short mi_7	  ; end of memory allocation table
   407                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   408 000003EA 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   409 000003EC 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   410 000003EE D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   411 000003F0 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   412 000003F2 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   413                                  mi_7:
   414                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   415 000003F4 BA00001000              	mov	edx, MEM_ALLOC_TBL
   416                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   417                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   418 000003F9 668B0D[606B0000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   419 00000400 89D7                    	mov	edi, edx
   420 00000402 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   421                                  				  ; byte offset in M.A.T.
   422                                  				  ; (1 M.A.T. byte points to 
   423                                  				  ;	      32768 bytes)
   424                                  				  ; Note: MEM_ALLOC_TBL address 
   425                                  				  ; must be aligned on 128 KB 
   426                                  				  ; boundary!
   427 00000405 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   428                                  	; eax = 0
   429 00000407 290D[506B0000]          	sub	[free_pages], ecx ; 07/11/2014
   430                                  mi_8:
   431 0000040D 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   432                                  	;dec	bl
   433 00000410 FEC9                    	dec	cl
   434 00000412 7404                    	jz	short mi_9
   435 00000414 FEC0                    	inc	al
   436 00000416 EBF5                    	jmp	short mi_8
   437                                  mi_9:
   438                                  	;
   439                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   440                                  	;		(allocate pages for system page tables)
   441                                  
   442                                  	; edx = MEM_ALLOC_TBL
   443 00000418 8B0D[4C6B0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   444 0000041E 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   445 00000424 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   446                                  				 ; page table count (PDE count)
   447                                  	;
   448 00000427 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   449                                  	;
   450 00000428 41                      	inc	ecx		 ; +1 for kernel page directory	
   451                                  	;
   452 00000429 290D[506B0000]          	sub	[free_pages], ecx ; 07/11/2014
   453                                  	;
   454 0000042F 8B35[486B0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   455 00000435 C1EE0C                  	shr	esi, 12		 ; convert to page number
   456                                  mi_10:
   457 00000438 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   458 0000043A 89C3                    	mov	ebx, eax
   459 0000043C C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   460 0000043F 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   461                                  				 ;   to align on dword boundary
   462 00000442 83E01F                  	and	eax, 31		 ; set allocation bit position 
   463                                  				 ;  (bit 0 to bit 31)
   464                                  	;
   465 00000445 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   466                                  	;
   467 00000447 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   468                                  	;
   469 0000044A 46                      	inc	esi		 ; next page table
   470 0000044B E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   471                                  				 ; (ecx = page table count + 1)		
   472                                  	;
   473 0000044D 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   474                                  	;
   475                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   476                                  	;
   477                                  	; Initialize Kernel's Page Directory
   478 0000044E 8B3D[486B0000]          	mov	edi, [k_page_dir]
   479 00000454 89F8                    	mov	eax, edi
   480 00000456 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   481                                  		     	      ; supervisor + read&write + present
   482 00000458 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   483                                  mi_11:
   484 0000045A 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   485                                  			        ; EAX points to next page table
   486 0000045F AB                      	stosd
   487 00000460 E2F8                    	loop	mi_11
   488 00000462 29C0                    	sub	eax, eax	; Empty PDE
   489 00000464 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   490 00000468 29D1                    	sub	ecx, edx
   491 0000046A 7402                    	jz	short mi_12
   492 0000046C F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   493                                  	;
   494                                  	; Initialization of Kernel's Page Directory is OK, here.
   495                                  mi_12:
   496                                  	; Initialize Kernel's Page Tables
   497                                  	;
   498                                  	; (EDI points to address of page table 0)
   499                                  	; eax = 0
   500 0000046E 8B0D[4C6B0000]          	mov	ecx, [memory_size] ; memory size in pages
   501 00000474 89CA                    	mov	edx, ecx	; (***)
   502 00000476 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   503                                  			     ; supervisor + read&write + present 	
   504                                  mi_13:
   505 00000478 AB                      	stosd
   506 00000479 0500100000              	add	eax, 4096	
   507 0000047E E2F8                    	loop	mi_13	
   508 00000480 6681E2FF03              	and	dx, 1023	; (***)
   509 00000485 740B                    	jz	short mi_14
   510 00000487 66B90004                	mov	cx, 1024	
   511 0000048B 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   512 0000048E 31C0                    	xor	eax, eax
   513 00000490 F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   514                                  				; of the last page table
   515                                  mi_14:
   516                                  	;  Initialization of Kernel's Page Tables is OK, here.
   517                                  	;
   518 00000492 89F8                    	mov	eax, edi	; end of the last page table page
   519                                  			        ; (beginging of user space pages)
   520 00000494 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   521 00000497 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   522                                  				; aligning on dword boundary	
   523                                  	 
   524 00000499 A3[5C6B0000]            	mov	[first_page], eax
   525 0000049E A3[546B0000]            	mov	[next_page], eax ; The first free page pointer
   526                                  				 ; for user programs
   527                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   528                                  	;
   529                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   530                                  	;
   531                                  	
   532                                  	; Enable paging
   533                                  	;
   534 000004A3 A1[486B0000]                    mov     eax, [k_page_dir]
   535 000004A8 0F22D8                  	mov	cr3, eax
   536 000004AB 0F20C0                  	mov	eax, cr0
   537 000004AE 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   538 000004B3 0F22C0                  	mov	cr0, eax
   539                                          ;jmp    KCODE:StartPMP
   540                                  
   541 000004B6 EA                      	db 0EAh 		; Opcode for far jump
   542 000004B7 [BD040000]                      dd StartPMP		; 32 bit offset
   543 000004BB 0800                    	dw KCODE		; kernel code segment descriptor
   544                                  
   545                                  
   546                                  StartPMP:
   547                                  	; 06/11//2014
   548                                  	; Clear video page 0
   549                                  	;
   550                                  	; Temporary Code
   551                                  	;
   552 000004BD B9E8030000              	mov	ecx, 80*25/2
   553 000004C2 BF00800B00              	mov	edi, 0B8000h
   554 000004C7 31C0                    	xor	eax, eax	; black background, black fore color
   555 000004C9 F3AB                    	rep	stosd
   556                                  	
   557                                  	; 19/08/2014
   558                                  	; Kernel Base Address = 0
   559                                  	; It is mapped to (physically) 0 in the page table.
   560                                  	; So, here is exactly 'StartPMP' address.
   561                                  	;
   562                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   563                                  	;;mov	esi, msgPM
   564                                  	;; 14/08/2015 (kernel version message will appear
   565                                  	;;	       when protected mode and paging is enabled)
   566 000004CB B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   567 000004CD BE[A0660000]            	mov	esi, msgKVER
   568 000004D2 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   569                                  	; 20/08/2014
   570 000004D7 E896010000              	call	printk
   571                                  
   572                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   573                                  	; // Set IRQ offsets
   574                                  	;
   575                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   576                                  	;
   577                                  					;; ICW1
   578 000004DC B011                    	mov	al, 11h			; Initialization sequence
   579 000004DE E620                    	out	20h, al			; 	8259A-1
   580                                  	; jmp 	$+2
   581 000004E0 E6A0                    	out	0A0h, al		; 	8259A-2
   582                                  					;; ICW2
   583 000004E2 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   584 000004E4 E621                    	out	21h, al			;	for 8259A-1
   585                                  	; jmp 	$+2
   586 000004E6 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   587 000004E8 E6A1                    	out	0A1h, al		; 	for 8259A-2
   588                                  					;
   589 000004EA B004                    	mov	al, 04h			;; ICW3
   590 000004EC E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   591                                  	; jmp 	$+2
   592 000004EE B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   593 000004F0 E6A1                    	out	0A1h, al		;
   594                                  					;; ICW4
   595 000004F2 B001                    	mov	al, 01h	 		;
   596 000004F4 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   597                                  	; jmp 	$+2
   598 000004F6 E6A1                    	out	0A1h, al		;	for both chips.
   599                                  
   600                                  	;mov	al, 0FFh	; mask off all interrupts for now
   601                                  	;out	21h, al
   602                                  	;; jmp 	$+2
   603                                  	;out	0A1h, al
   604                                  
   605                                  	; 02/04/2015
   606                                  	; 26/03/2015 System call (INT 30h) modification
   607                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   608                                  	;
   609                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   610                                  	;  setup_idt:
   611                                  	;
   612                                          ;; 16/02/2015
   613                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   614                                  	; 21/08/2014 (timer_int)
   615 000004F8 BE[6C630000]            	mov	esi, ilist
   616 000004FD 8D3D[E0680000]          	lea	edi, [idt]
   617                                  	; 26/03/2015
   618 00000503 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   619                                  	; 02/04/2015
   620 00000508 BB00000800              	mov	ebx, 80000h
   621                                  rp_sidt1:
   622 0000050D AD                      	lodsd
   623 0000050E 89C2                    	mov	edx, eax
   624 00000510 66BA008E                	mov	dx, 8E00h
   625 00000514 6689C3                  	mov	bx, ax
   626 00000517 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   627                                         			        ; /* interrupt gate - dpl=0, present */
   628 00000519 AB                      	stosd	; selector & offset bits 0-15 	
   629 0000051A 89D0                    	mov	eax, edx
   630 0000051C AB                      	stosd	; attributes & offset bits 16-23
   631 0000051D E2EE                    	loop	rp_sidt1
   632 0000051F B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   633                                  rp_sidt2:
   634 00000521 AD                      	lodsd
   635 00000522 21C0                    	and	eax, eax
   636 00000524 7413                    	jz	short rp_sidt3
   637 00000526 89C2                    	mov	edx, eax
   638 00000528 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   639 0000052C 6689C3                  	mov	bx, ax
   640 0000052F 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   641 00000531 AB                      	stosd
   642 00000532 89D0                    	mov	eax, edx
   643 00000534 AB                      	stosd
   644 00000535 E2EA                    	loop	rp_sidt2
   645 00000537 EB16                    	jmp	short sidt_OK
   646                                  rp_sidt3:
   647 00000539 B8[A0090000]            	mov	eax, ignore_int
   648 0000053E 89C2                    	mov	edx, eax
   649 00000540 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   650 00000544 6689C3                  	mov	bx, ax
   651 00000547 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   652                                  rp_sidt4:
   653 00000549 AB                      	stosd
   654 0000054A 92                      	xchg	eax, edx
   655 0000054B AB                      	stosd
   656 0000054C 92                      	xchg	edx, eax
   657 0000054D E2FA                    	loop	rp_sidt4
   658                                  sidt_OK: 
   659 0000054F 0F011D[66630000]        	lidt 	[idtd]
   660                                  	;
   661                                  	; TSS descriptor setup ; 24/03/2015
   662 00000556 B8[E06A0000]            	mov	eax, task_state_segment
   663 0000055B 66A3[5A630000]          	mov	[gdt_tss0], ax
   664 00000561 C1C010                  	rol	eax, 16
   665 00000564 A2[5C630000]            	mov	[gdt_tss1], al
   666 00000569 8825[5F630000]          	mov	[gdt_tss2], ah
   667 0000056F 66C705[466B0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   667 00000577 00                 
   668                                  		; 
   669                                  		; IO Map Base address (When this address points
   670                                  		; to end of the TSS, CPU does not use IO port 
   671                                  		; permission bit map for RING 3 IO permissions, 
   672                                  		; access to any IO ports in ring 3 will be forbidden.)
   673                                   		;
   674                                  	;mov	[tss.esp0], esp ; TSS offset 4
   675                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   676 00000578 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   677                                  			 ; occurs (or a system call -software INT- is requested)
   678                                  			 ; while cpu running in ring 3 (in user mode).				
   679                                  			 ; (Kernel stack pointer and segment will be loaded
   680                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   681 0000057C 0F00D8                  	ltr	ax  ; Load task register
   682                                  	;
   683                                  esp0_set0:
   684                                  	; 30/07/2015
   685 0000057F 8B0D[4C6B0000]          	mov 	ecx, [memory_size] ; memory size in pages
   686 00000585 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   687 00000588 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   688                                  			  ; (kernel mode virtual address)
   689 0000058E 7605                    	jna	short esp0_set1
   690                                  	;
   691                                  	; If available memory > CORE (end of the 1st 4 MB)
   692                                  	; set stack pointer to CORE
   693                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   694                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   695 00000590 B900004000              	mov	ecx, CORE
   696                                  esp0_set1:
   697 00000595 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   698                                  esp0_set_ok:
   699                                  	; 30/07/2015 (**tss.esp0**) 
   700 00000597 8925[E46A0000]          	mov	[tss.esp0], esp
   701 0000059D 66C705[E86A0000]10-             mov     word [tss.ss0], KDATA
   701 000005A5 00                 
   702                                  	; 14/08/2015
   703                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   704                                  	;
   705                                  	;cli	; Disable interrupts (for CPU)
   706                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   707                                  	;
   708 000005A6 30C0                    	xor	al, al		; Enable all hardware interrupts!
   709 000005A8 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   710 000005AA EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   711 000005AC E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   712                                  				; (Even if related hardware component
   713                                  				;  does not exist!)
   714                                  	; Enable NMI 
   715 000005AE B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   716 000005B0 E670                    	out  	70h, al
   717                                  	; 23/02/2015
   718 000005B2 90                      	nop
   719 000005B3 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   720                                  				; for preventing unknown state (!?)
   721                                  	;
   722                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   723                                  	;
   724                                  	; 02/09/2014
   725 000005B5 6631DB                  	xor	bx, bx
   726 000005B8 66BA0002                	mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   727 000005BC E83C0F0000              	call	set_cpos
   728                                  	;
   729                                  	; 06/11/2014
   730                                  	; Temporary Code
   731                                  	;
   732 000005C1 E8B5100000              	call	memory_info
   733                                  	; 14/08/2015
   734                                  	;call getch ; 28/02/2015
   735                                  drv_init:
   736 000005C6 FB                      	sti	; Enable Interrupts 
   737                                  	; 06/02/2015
   738 000005C7 8B15[40660000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   739 000005CD 668B1D[3E660000]        	mov	bx, [fd0_type] ; fd0, fd1
   740                                  	; 22/02/2015
   741 000005D4 6621DB                  	and	bx, bx
   742 000005D7 751B                    	jnz	short di1
   743                                  	;
   744 000005D9 09D2                    	or 	edx, edx
   745 000005DB 7529                    	jnz	short di2
   746                                  	;
   747                                  setup_error:
   748 000005DD BE[87670000]            	mov 	esi, setup_error_msg
   749                                  psem:	
   750 000005E2 AC                      	lodsb
   751 000005E3 08C0                    	or	al, al
   752                                  	;jz	short haltx ; 22/02/2015
   753 000005E5 7426                    	jz	short di3
   754 000005E7 56                      	push	esi
   755 000005E8 31DB                    	xor	ebx, ebx ; 0
   756                                  			; Video page 0 (bl=0)
   757 000005EA B407                    	mov	ah, 07h ; Black background, 
   758                                  			; light gray forecolor
   759 000005EC E8020E0000              	call	write_tty
   760 000005F1 5E                      	pop	esi
   761 000005F2 EBEE                    	jmp	short psem
   762                                  
   763                                  di1:
   764                                  	; supress 'jmp short T6'
   765                                  	;  (activate fdc motor control code)
   766 000005F4 66C705[F3060000]90-     	mov	word [T5], 9090h ; nop
   766 000005FC 90                 
   767                                  	;
   768                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   769                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   770                                  	;stosw
   771                                  	;mov 	ax, cs
   772                                  	;stosw
   773                                  	;; 16/02/2015
   774                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   775                                  	;
   776 000005FD E88F1F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   777                                  	;
   778 00000602 09D2                    	or	edx, edx
   779 00000604 7407                            jz      short di3
   780                                  di2:
   781 00000606 E8CB1F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   782 0000060B 72D0                            jc      short setup_error
   783                                  di3:
   784 0000060D E83D100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   785                                  	;
   786 00000612 E86A5C0000              	call	display_disks ; 07/03/2015  (Temporary)
   787                                  ;haltx:
   788                                  	; 14/08/2015
   789                                  	;call	getch ; 22/02/2015
   790 00000617 FB                      	sti	; Enable interrupts (for CPU)
   791                                  	; 14/08/2015
   792                                  	;mov 	ecx, 0FFFFFFFh
   793                                  	; 16/02/2022
   794 00000618 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   795                                  md_info_msg_wait:
   796 0000061D 51                      	push 	ecx
   797 0000061E B001                    	mov	al, 1
   798 00000620 8A25[766B0000]          	mov 	ah, [ptty] ; active (current) video page
   799 00000626 E89F590000              	call	getc_n
   800 0000062B 59                      	pop	ecx
   801 0000062C 7502                    	jnz	short md_info_msg_ok
   802 0000062E E2ED                    	loop	md_info_msg_wait
   803                                  md_info_msg_ok:
   804                                  	; 30/06/2015
   805 00000630 E8AC2C0000              	call	sys_init
   806                                  	;
   807                                  	;jmp 	cpu_reset ; 22/02/2015
   808                                  hang:  
   809                                  	; 23/02/2015
   810                                  	;sti			; Enable interrupts
   811 00000635 F4                      	hlt
   812                                  	;
   813                                  	;nop
   814                                  	;; 03/12/2014
   815                                  	;; 28/08/2014
   816                                  	;mov	ah, 11h
   817                                  	;call	getc
   818                                  	;jz      _c8
   819                                  	;
   820                                  	; 23/02/2015
   821                                  	; 06/02/2015
   822                                  	; 07/09/2014
   823 00000636 31DB                    	xor	ebx, ebx
   824 00000638 8A1D[766B0000]          	mov	bl, [ptty]	; active_page
   825 0000063E 89DE                    	mov	esi, ebx
   826 00000640 66D1E6                  	shl 	si, 1
   827 00000643 81C6[786B0000]          	add	esi, ttychr
   828 00000649 668B06                  	mov	ax, [esi]
   829 0000064C 6621C0                  	and	ax, ax
   830                                  	;jz	short _c8
   831 0000064F 74E4                    	jz	short hang
   832 00000651 66C7060000              	mov	word [esi], 0
   833 00000656 80FB03                  	cmp	bl, 3		; Video page 3
   834                                  	;jb	short _c8
   835 00000659 72DA                    	jb	short hang
   836                                  	;	
   837                                  	; 02/09/2014
   838 0000065B B40E                    	mov	ah, 0Eh		; Yellow character 
   839                                  				; on black background
   840                                  	; 07/09/2014
   841                                  nxtl:
   842 0000065D 6653                    	push	bx
   843                                  	;
   844                                  	;xor	bx, bx		; bl = 0 (video page 0)
   845                                  				; bh = 0 (video mode)
   846                                  				; Retro UNIX 386 v1 - Video Mode 0
   847                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   848 0000065F 6650                    	push	ax
   849 00000661 E88D0D0000              	call 	write_tty
   850 00000666 6658                    	pop	ax
   851 00000668 665B                    	pop	bx ; 07/09/2014
   852 0000066A 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   853                                  	;jne	short _c8
   854 0000066C 75C7                    	jne	short hang
   855 0000066E B00A                    	mov	al, 0Ah		; next line
   856 00000670 EBEB                    	jmp	short nxtl
   857                                  	
   858                                  ;_c8:
   859                                  ;	; 25/08/2014
   860                                  ;	cli				; Disable interrupts
   861                                  ;	mov	al, [scounter + 1]
   862                                  ;	and	al, al
   863                                  ;	jnz	hang
   864                                  ;	call	rtc_p
   865                                  ;	jmp     hang
   866                                  
   867                                  
   868                                  	; 27/08/2014
   869                                  	; 20/08/2014
   870                                  printk:
   871                                          ;mov    edi, [scr_row]
   872                                  pkl:
   873 00000672 AC                      	lodsb
   874 00000673 08C0                    	or 	al, al
   875 00000675 7404                    	jz	short pkr
   876 00000677 66AB                    	stosw
   877 00000679 EBF7                    	jmp	short pkl
   878                                  pkr:
   879 0000067B C3                      	retn
   880                                  
   881                                  ; 25/07/2015
   882                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   883                                  ; 17/02/2015
   884                                  ; 06/02/2015 (unix386.s)
   885                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   886                                  ;
   887                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   888                                  ;
   889                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   890                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   891                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   892                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   893                                  ;									       :
   894                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   895                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   896                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   897                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   898                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   899                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   900                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   901                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   902                                  ;-------------------------------------------------------------------------------
   903                                  ;
   904                                  
   905                                  timer_int:	; IRQ 0
   906                                  ;int_08h:	; Timer
   907                                  	; 14/10/2015
   908                                  	; Here, we are simulating system call entry (for task switch)
   909                                  	; (If multitasking is enabled, 
   910                                  	; 'clock' procedure may jump to 'sysrelease')
   911 0000067C 1E                      	push	ds
   912 0000067D 06                      	push	es
   913 0000067E 0FA0                    	push	fs
   914 00000680 0FA8                    	push	gs
   915 00000682 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   916 00000683 66B91000                	mov     cx, KDATA
   917 00000687 8ED9                            mov     ds, cx
   918 00000689 8EC1                            mov     es, cx
   919 0000068B 8EE1                            mov     fs, cx
   920 0000068D 8EE9                            mov     gs, cx
   921                                  	;
   922 0000068F 0F20D9                  	mov	ecx, cr3
   923 00000692 890D[35070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   924                                  	;
   925 00000698 3B0D[486B0000]          	cmp 	ecx, [k_page_dir]
   926 0000069E 741F                    	je	short T3
   927                                  	;
   928                                  	; timer interrupt has been occurred while OS is in user mode
   929 000006A0 A3[F86E0000]            	mov 	[u.r0], eax
   930 000006A5 89E1                    	mov	ecx, esp
   931 000006A7 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   932 000006AA 890D[F06E0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   933 000006B0 8925[F46E0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   934                                  	;
   935 000006B6 8B0D[486B0000]          	mov	ecx, [k_page_dir]
   936 000006BC 0F22D9                  	mov	cr3, ecx
   937                                  T3:
   938 000006BF FB                      	sti				; INTERRUPTS BACK ON
   939 000006C0 66FF05[C46B0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   940 000006C7 7507                    	JNZ	short T4		; GO TO TEST_DAY
   941 000006C9 66FF05[C66B0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   942                                  T4:					; TEST_DAY
   943 000006D0 66833D[C66B0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   944 000006D8 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   945 000006DA 66813D[C46B0000]B0-     	CMP	word [TIMER_LOW],0B0H
   945 000006E2 00                 
   946 000006E3 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   947                                  
   948                                  ;-----	TIMER HAS GONE 24 HOURS
   949                                  	;;SUB	AX,AX
   950                                  	;MOV	[TIMER_HIGH],AX
   951                                  	;MOV	[TIMER_LOW],AX
   952 000006E5 29C0                    	sub	eax, eax
   953 000006E7 A3[C46B0000]            	mov	[TIMER_LH], eax
   954                                  	;	
   955 000006EC C605[C86B0000]01        	MOV	byte [TIMER_OFL],1
   956                                  
   957                                  ;-----	TEST FOR DISKETTE TIME OUT
   958                                  
   959                                  T5:
   960                                  	; 23/12/2014
   961 000006F3 EB1D                    	jmp	short T6		; will be replaced with nop, nop
   962                                  					; (9090h) if a floppy disk
   963                                  					; is detected.
   964                                  	;mov	al,[CS:MOTOR_COUNT]
   965 000006F5 A0[CB6B0000]            	mov	al, [MOTOR_COUNT]
   966 000006FA FEC8                    	dec	al
   967                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   968 000006FC A2[CB6B0000]            	mov	[MOTOR_COUNT], al
   969                                  	;mov	[ORG_MOTOR_COUNT], al
   970 00000701 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   971 00000703 B0F0                    	mov 	al,0F0h
   972                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   973 00000705 2005[CA6B0000]          	and	[MOTOR_STATUS], al
   974                                  	;and	[ORG_MOTOR_STATUS], al
   975 0000070B B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   976                                  					; bit 2 = enable controller
   977                                  					;	1 = normal operation
   978                                  					;	0 = reset	
   979                                  					; bit 0, 1 = drive select
   980                                  					; bit 4-7 = motor running bits 
   981 0000070D 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
   982 00000711 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
   983                                  T6:	
   984                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
   985                                  					; TIMER TICK INTERRUPT
   986                                  	;;inc	word [wait_count] ;;27/02/2015
   987                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
   988                                  	;;;;cli
   989                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
   990 00000712 FF15[2D070000]          	call	[x_timer] ; 14/05/2015
   991                                  T7:
   992                                  	; 14/10/2015
   993 00000718 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
   994 0000071A FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
   995 0000071B E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
   996                                  	;
   997 0000071D A1[35070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
   998 00000722 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
   999                                  	;
  1000 00000725 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1001                                  	;
  1002 00000726 0FA9                    	pop	gs
  1003 00000728 0FA1                    	pop	fs
  1004 0000072A 07                      	pop	es
  1005 0000072B 1F                      	pop	ds
  1006 0000072C CF                      	iretd	; return from interrupt
  1007                                  
  1008                                  
  1009                                  ; ////////////////
  1010                                  
  1011                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1012                                  x_timer:
  1013 0000072D [39070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1014                                  	;dd	clock
  1015                                  
  1016                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1017                                  x_rtci:
  1018 00000731 [790A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1019                                  
  1020                                  ; 14/10/2015
  1021 00000735 00000000                cr3reg: dd 0
  1022                                  
  1023                                  	; 06/02/2015
  1024                                  	; 07/09/2014
  1025                                  	; 21/08/2014
  1026                                  u_timer:
  1027                                  	; 12/02/2022
  1028                                  ;timer_int:	; IRQ 0
  1029                                  	; 06/02/2015
  1030                                  	;push	eax
  1031                                  	;push	edx
  1032                                  	;push	ecx
  1033                                  	;push	ebx
  1034                                  	;push	ds
  1035                                  	;push	es
  1036                                  	;mov	eax, KDATA
  1037                                  	;mov	ds, ax
  1038                                  	;mov	es, ax
  1039 00000739 FF05[8C6B0000]          	inc	dword [tcount]
  1040 0000073F BB[10670000]            	mov	ebx, tcountstr + 4
  1041 00000744 66A1[8C6B0000]          	mov	ax, [tcount]
  1042 0000074A B90A000000              	mov	ecx, 10
  1043                                  rp_divtcnt:
  1044 0000074F 31D2                    	xor	edx, edx
  1045 00000751 F7F1                    	div	ecx
  1046 00000753 80C230                  	add	dl, 30h
  1047 00000756 8813                    	mov	[ebx], dl
  1048 00000758 6609C0                  	or	ax, ax
  1049 0000075B 7403                    	jz	short print_lzero
  1050 0000075D 4B                      	dec	ebx
  1051 0000075E EBEF                    	jmp	short rp_divtcnt
  1052                                  print_lzero:
  1053 00000760 81FB[0C670000]          	cmp	ebx, tcountstr
  1054 00000766 7606                    	jna	short print_tcount
  1055 00000768 4B                      	dec	ebx
  1056 00000769 C60330                   	mov	byte [ebx], 30h
  1057 0000076C EBF2                    	jmp	short print_lzero
  1058                                  print_tcount:
  1059 0000076E 56                      	push	esi
  1060 0000076F 57                      	push	edi
  1061 00000770 BE[E8660000]            	mov	esi, timer_msg ; Timer interrupt message
  1062                                  	;; 07/09/2014
  1063                                  	;mov	bx, 1		; Video page 1
  1064                                  	; 12/02/2022
  1065 00000775 66BB0600                	mov	bx, 6		; Video page 6
  1066                                  ptmsg:
  1067 00000779 AC                      	lodsb
  1068 0000077A 08C0                    	or	al, al
  1069 0000077C 740F                    	jz	short ptmsg_ok
  1070 0000077E 56                      	push	esi
  1071 0000077F 6653                    	push	bx
  1072 00000781 B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1073 00000783 E86B0C0000              	call 	write_tty
  1074 00000788 665B                    	pop	bx
  1075 0000078A 5E                      	pop	esi
  1076 0000078B EBEC                    	jmp	short ptmsg
  1077                                  	;; 27/08/2014
  1078                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1079                                  	;call	printk
  1080                                  	;
  1081                                  ptmsg_ok:
  1082                                  	; 07/09/2014
  1083 0000078D 6631D2                  	xor	dx, dx		; column 0, row 0
  1084 00000790 E8680D0000              	call	set_cpos	; set cursor position to 0,0 
  1085                                  	; 23/02/2015
  1086                                  	; 25/08/2014
  1087                                  	;mov	ebx, scounter		; (seconds counter)
  1088                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1089                                  ;	dec	byte [scounter+1]
  1090                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1091                                  ;	jns	short u_timer_retn
  1092                                  	; 26/02/2015
  1093                                  ;	call	rtc_p
  1094                                  ;	mov	ebx, scounter		; (seconds counter)
  1095                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1096                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1097                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1098                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1099                                  ;	mov	byte [ebx], 5
  1100                                  ;	inc	byte [ebx+1] ; 19
  1101                                  ;;timer_eoi:
  1102                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1103                                  ;;	out	20h, al	; 8259 PORT
  1104                                  	;
  1105                                  ;u_timer_retn:  ; 06/02/2015
  1106 00000795 5F                      	pop	edi
  1107 00000796 5E                      	pop	esi
  1108                                  	;pop	es
  1109                                  	;pop	ds
  1110                                  	;pop	ebx
  1111                                  	;pop	ecx
  1112                                  	;pop	edx
  1113                                  	;pop	eax
  1114                                  	;iret
  1115 00000797 C3                      	retn	; 06/02/2015
  1116                                  
  1117                                  	; 28/08/2014
  1118                                  irq0:
  1119 00000798 6A00                            push 	dword 0
  1120 0000079A EB48                    	jmp	short which_irq
  1121                                  irq1:
  1122 0000079C 6A01                            push 	dword 1
  1123 0000079E EB44                    	jmp	short which_irq
  1124                                  irq2:
  1125 000007A0 6A02                            push 	dword 2
  1126 000007A2 EB40                    	jmp	short which_irq
  1127                                  irq3:
  1128                                  	; 20/11/2015
  1129                                  	; 24/10/2015
  1130 000007A4 2EFF15[203A0000]        	call	dword [cs:com2_irq3]
  1131 000007AB 6A03                    	push 	dword 3
  1132 000007AD EB35                    	jmp	short which_irq
  1133                                  irq4:
  1134                                  	; 20/11/2015
  1135                                  	; 24/10/2015
  1136 000007AF 2EFF15[1C3A0000]        	call	dword [cs:com1_irq4]
  1137 000007B6 6A04                            push 	dword 4
  1138 000007B8 EB2A                    	jmp	short which_irq
  1139                                  irq5:
  1140 000007BA 6A05                            push 	dword 5
  1141 000007BC EB26                    	jmp	short which_irq
  1142                                  irq6:
  1143 000007BE 6A06                            push 	dword 6
  1144 000007C0 EB22                    	jmp	short which_irq
  1145                                  irq7:
  1146 000007C2 6A07                            push 	dword 7
  1147 000007C4 EB1E                    	jmp	short which_irq
  1148                                  irq8:
  1149 000007C6 6A08                            push 	dword 8
  1150 000007C8 EB1A                    	jmp	short which_irq
  1151                                  irq9:
  1152 000007CA 6A09                            push 	dword 9
  1153 000007CC EB16                    	jmp	short which_irq
  1154                                  irq10:
  1155 000007CE 6A0A                            push 	dword 10
  1156 000007D0 EB12                    	jmp	short which_irq
  1157                                  irq11:
  1158 000007D2 6A0B                            push 	dword 11
  1159 000007D4 EB0E                    	jmp	short which_irq
  1160                                  irq12:
  1161 000007D6 6A0C                            push 	dword 12
  1162 000007D8 EB0A                    	jmp	short which_irq
  1163                                  irq13:
  1164 000007DA 6A0D                            push 	dword 13
  1165 000007DC EB06                    	jmp	short which_irq
  1166                                  irq14:
  1167 000007DE 6A0E                            push 	dword 14
  1168 000007E0 EB02                    	jmp	short which_irq
  1169                                  irq15:
  1170 000007E2 6A0F                            push 	dword 15
  1171                                  	;jmp	short which_irq
  1172                                  
  1173                                  	; 19/10/2015
  1174                                  	; 29/08/2014
  1175                                  	; 21/08/2014
  1176                                  which_irq:
  1177 000007E4 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1178 000007E7 53                      	push	ebx
  1179 000007E8 56                      	push	esi
  1180 000007E9 57                      	push	edi
  1181 000007EA 1E                      	push 	ds
  1182 000007EB 06                      	push 	es
  1183                                  	;
  1184 000007EC 88C3                    	mov	bl, al
  1185                                  	;
  1186 000007EE B810000000              	mov	eax, KDATA
  1187 000007F3 8ED8                    	mov	ds, ax
  1188 000007F5 8EC0                    	mov	es, ax
  1189                                  	; 19/10/2015
  1190 000007F7 FC                      	cld
  1191                                          ; 27/08/2014
  1192 000007F8 8105[98660000]A000-             add     dword [scr_row], 0A0h
  1192 00000800 0000               
  1193                                  	;
  1194 00000802 B417                    	mov	ah, 17h	; blue (1) background, 
  1195                                  			; light gray (7) forecolor
  1196 00000804 8B3D[98660000]                  mov     edi, [scr_row]
  1197 0000080A B049                    	mov	al, 'I'
  1198 0000080C 66AB                    	stosw
  1199 0000080E B052                    	mov	al, 'R'
  1200 00000810 66AB                    	stosw
  1201 00000812 B051                    	mov	al, 'Q'
  1202 00000814 66AB                    	stosw
  1203 00000816 B020                    	mov	al, ' '
  1204 00000818 66AB                    	stosw
  1205 0000081A 88D8                    	mov	al, bl
  1206 0000081C 3C0A                    	cmp	al, 10
  1207 0000081E 7208                    	jb	short iix
  1208 00000820 B031                    	mov	al, '1'
  1209 00000822 66AB                    	stosw
  1210 00000824 88D8                    	mov	al, bl
  1211 00000826 2C0A                    	sub	al, 10
  1212                                  iix:
  1213 00000828 0430                    	add	al, '0'
  1214 0000082A 66AB                    	stosw
  1215 0000082C B020                    	mov	al, ' '
  1216 0000082E 66AB                    	stosw
  1217 00000830 B021                    	mov	al, '!'
  1218 00000832 66AB                    	stosw
  1219 00000834 B020                    	mov	al, ' '
  1220 00000836 66AB                    	stosw
  1221                                  	; 23/02/2015
  1222 00000838 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1223 0000083B 0F868D010000            	jna	iiret
  1224 00000841 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1225 00000843 E6A0                    	out	0A0h, al ; the 2nd 8259
  1226 00000845 E984010000              	jmp     iiret
  1227                                  	;
  1228                                  	; 22/08/2014
  1229                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1230                                  	;out	20h, al	; 8259 PORT
  1231                                  	;
  1232                                  	;pop	es
  1233                                  	;pop	ds
  1234                                  	;pop	edi
  1235                                  	;pop	esi
  1236                                  	;pop	ebx
  1237                                  	;pop 	eax
  1238                                  	;iret
  1239                                  
  1240                                  	; 02/04/2015
  1241                                  	; 25/08/2014
  1242                                  exc0:
  1243 0000084A 6A00                            push 	dword 0
  1244 0000084C E990000000                      jmp     cpu_except
  1245                                  exc1:
  1246 00000851 6A01                            push 	dword 1
  1247 00000853 E989000000                      jmp     cpu_except
  1248                                  exc2:
  1249 00000858 6A02                            push 	dword 2
  1250 0000085A E982000000                      jmp     cpu_except
  1251                                  exc3:
  1252 0000085F 6A03                            push 	dword 3
  1253 00000861 EB7E                            jmp     cpu_except
  1254                                  exc4:
  1255 00000863 6A04                            push 	dword 4
  1256 00000865 EB7A                            jmp     cpu_except
  1257                                  exc5:
  1258 00000867 6A05                            push 	dword 5
  1259 00000869 EB76                            jmp     cpu_except
  1260                                  exc6:
  1261 0000086B 6A06                            push 	dword 6
  1262 0000086D EB72                            jmp     cpu_except
  1263                                  exc7:
  1264 0000086F 6A07                            push 	dword 7
  1265 00000871 EB6E                            jmp     cpu_except
  1266                                  exc8:
  1267                                  	; [esp] = Error code
  1268 00000873 6A08                            push 	dword 8
  1269 00000875 EB5C                            jmp     cpu_except_en
  1270                                  exc9:
  1271 00000877 6A09                            push 	dword 9
  1272 00000879 EB66                            jmp     cpu_except
  1273                                  exc10:
  1274                                  	; [esp] = Error code
  1275 0000087B 6A0A                            push 	dword 10
  1276 0000087D EB54                            jmp     cpu_except_en
  1277                                  exc11:
  1278                                  	; [esp] = Error code
  1279 0000087F 6A0B                            push 	dword 11
  1280 00000881 EB50                            jmp     cpu_except_en
  1281                                  exc12:
  1282                                  	; [esp] = Error code
  1283 00000883 6A0C                            push 	dword 12
  1284 00000885 EB4C                            jmp     cpu_except_en
  1285                                  exc13:
  1286                                  	; [esp] = Error code
  1287 00000887 6A0D                            push 	dword 13
  1288 00000889 EB48                            jmp     cpu_except_en
  1289                                  exc14:
  1290                                  	; [esp] = Error code
  1291 0000088B 6A0E                            push 	dword 14
  1292 0000088D EB44                    	jmp	short cpu_except_en
  1293                                  exc15:
  1294 0000088F 6A0F                            push 	dword 15
  1295 00000891 EB4E                            jmp     cpu_except
  1296                                  exc16:
  1297 00000893 6A10                            push 	dword 16
  1298 00000895 EB4A                            jmp     cpu_except
  1299                                  exc17:
  1300                                  	; [esp] = Error code
  1301 00000897 6A11                            push 	dword 17
  1302 00000899 EB38                    	jmp	short cpu_except_en
  1303                                  exc18:
  1304 0000089B 6A12                            push 	dword 18
  1305 0000089D EB42                    	jmp	short cpu_except
  1306                                  exc19:
  1307 0000089F 6A13                            push 	dword 19
  1308 000008A1 EB3E                    	jmp	short cpu_except
  1309                                  exc20:
  1310 000008A3 6A14                            push 	dword 20
  1311 000008A5 EB3A                    	jmp	short cpu_except
  1312                                  exc21:
  1313 000008A7 6A15                            push 	dword 21
  1314 000008A9 EB36                    	jmp	short cpu_except
  1315                                  exc22:
  1316 000008AB 6A16                            push 	dword 22
  1317 000008AD EB32                    	jmp	short cpu_except
  1318                                  exc23:
  1319 000008AF 6A17                            push 	dword 23
  1320 000008B1 EB2E                    	jmp	short cpu_except
  1321                                  exc24:
  1322 000008B3 6A18                            push 	dword 24
  1323 000008B5 EB2A                    	jmp	short cpu_except
  1324                                  exc25:
  1325 000008B7 6A19                            push 	dword 25
  1326 000008B9 EB26                    	jmp	short cpu_except
  1327                                  exc26:
  1328 000008BB 6A1A                            push 	dword 26
  1329 000008BD EB22                    	jmp	short cpu_except
  1330                                  exc27:
  1331 000008BF 6A1B                            push 	dword 27
  1332 000008C1 EB1E                    	jmp	short cpu_except
  1333                                  exc28:
  1334 000008C3 6A1C                            push 	dword 28
  1335 000008C5 EB1A                    	jmp	short cpu_except
  1336                                  exc29:
  1337 000008C7 6A1D                            push 	dword 29
  1338 000008C9 EB16                    	jmp	short cpu_except
  1339                                  exc30:
  1340 000008CB 6A1E                            push 	dword 30
  1341 000008CD EB04                    	jmp	short cpu_except_en
  1342                                  exc31:
  1343 000008CF 6A1F                            push 	dword 31
  1344 000008D1 EB0E                            jmp     short cpu_except
  1345                                  
  1346                                  	; 19/10/2015
  1347                                  	; 19/09/2015
  1348                                  	; 01/09/2015
  1349                                  	; 28/08/2015
  1350                                  	; 28/08/2014
  1351                                  cpu_except_en:
  1352 000008D3 87442404                	xchg	eax, [esp+4] ; Error code
  1353 000008D7 36A3[B87F0000]          	mov	[ss:error_code], eax
  1354 000008DD 58                      	pop	eax  ; Exception number
  1355 000008DE 870424                  	xchg	eax, [esp]
  1356                                  		; eax = eax before exception
  1357                                  		; [esp] -> exception number
  1358                                  		; [esp+4] -> EIP to return
  1359                                  	; 19/10/2015
  1360                                  	; 19/09/2015
  1361                                  	; 01/09/2015
  1362                                  	; 28/08/2015
  1363                                  	; 29/08/2014
  1364                                  	; 28/08/2014
  1365                                  	; 25/08/2014
  1366                                  	; 21/08/2014
  1367                                  cpu_except:	; CPU Exceptions
  1368 000008E1 FC                      	cld
  1369 000008E2 870424                  	xchg	eax, [esp] 
  1370                                  		; eax = Exception number
  1371                                  		; [esp] = eax (before exception)	
  1372 000008E5 53                      	push	ebx
  1373 000008E6 56                      	push	esi
  1374 000008E7 57                      	push	edi
  1375 000008E8 1E                      	push 	ds
  1376 000008E9 06                      	push 	es
  1377                                  	; 28/08/2015
  1378 000008EA 66BB1000                	mov	bx, KDATA
  1379 000008EE 8EDB                    	mov	ds, bx
  1380 000008F0 8EC3                    	mov	es, bx
  1381 000008F2 0F20DB                  	mov	ebx, cr3
  1382 000008F5 53                      	push	ebx ; (*) page directory
  1383                                  	; 19/10/2015
  1384 000008F6 FC                      	cld
  1385                                  	; 25/03/2015
  1386 000008F7 8B1D[486B0000]          	mov	ebx, [k_page_dir]
  1387 000008FD 0F22DB                  	mov	cr3, ebx
  1388                                  	; 28/08/2015
  1389 00000900 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1390 00000903 7512                    	jne	short cpu_except_nfp
  1391 00000905 E891270000              	call	page_fault_handler
  1392 0000090A 21C0                    	and 	eax, eax
  1393 0000090C 0F84B8000000                    jz	iiretp ; 01/09/2015
  1394 00000912 B80E000000              	mov	eax, 0Eh ; 14
  1395                                  cpu_except_nfp:
  1396                                  	; 02/04/2015
  1397 00000917 BB[35060000]            	mov	ebx, hang
  1398 0000091C 875C241C                	xchg	ebx, [esp+28]
  1399                                  		; EIP (points to instruction which faults)
  1400                                  	  	; New EIP (hang)
  1401 00000920 891D[BC7F0000]          	mov	[FaultOffset], ebx
  1402 00000926 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1403 0000092E 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1404                                  	;
  1405 00000936 88C4                    	mov	ah, al
  1406 00000938 240F                    	and	al, 0Fh
  1407 0000093A 3C09                    	cmp	al, 9
  1408 0000093C 7602                    	jna	short h1ok
  1409 0000093E 0407                    	add	al, 'A'-':'
  1410                                  h1ok:
  1411 00000940 D0EC                    	shr	ah, 1
  1412 00000942 D0EC                    	shr	ah, 1
  1413 00000944 D0EC                    	shr	ah, 1
  1414 00000946 D0EC                    	shr	ah, 1
  1415 00000948 80FC09                  	cmp	ah, 9
  1416 0000094B 7603                    	jna	short h2ok
  1417 0000094D 80C407                  	add	ah, 'A'-':'
  1418                                  h2ok:	
  1419 00000950 86E0                    	xchg 	ah, al	
  1420 00000952 66053030                	add	ax, '00'
  1421 00000956 66A3[24670000]          	mov	[excnstr], ax
  1422                                  	;
  1423                                  	; 29/08/2014
  1424 0000095C A1[BC7F0000]            	mov	eax, [FaultOffset]
  1425 00000961 51                      	push	ecx
  1426 00000962 52                      	push	edx
  1427 00000963 89E3                    	mov	ebx, esp
  1428                                  	; 28/08/2015
  1429 00000965 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1430                                  			  ; to hexadecimal string
  1431                                  	;mov	ecx, 10	    ; divisor to convert	
  1432                                  			    ; binary number to decimal string
  1433                                  b2d1:
  1434 0000096A 31D2                    	xor	edx, edx
  1435 0000096C F7F1                    	div	ecx
  1436 0000096E 6652                    	push	dx
  1437 00000970 39C8                    	cmp	eax, ecx
  1438 00000972 73F6                    	jnb	short b2d1
  1439 00000974 BF[2F670000]            	mov	edi, EIPstr ; EIP value
  1440                                  			    ; points to instruction which faults	
  1441                                  	; 28/08/2015
  1442 00000979 89C2                    	mov	edx, eax
  1443                                  b2d2:
  1444                                  	;add	al, '0'
  1445 0000097B 8A82[37170000]          	mov	al, [edx+hexchrs]
  1446 00000981 AA                      	stosb		    ; write hexadecimal digit to its place	
  1447 00000982 39E3                    	cmp	ebx, esp
  1448 00000984 7606                    	jna	short b2d3
  1449 00000986 6658                    	pop	ax
  1450 00000988 88C2                    	mov	dl, al
  1451 0000098A EBEF                    	jmp	short b2d2
  1452                                  b2d3:
  1453 0000098C B068                    	mov 	al, 'h' ; 28/08/2015
  1454 0000098E AA                      	stosb
  1455 0000098F B020                    	mov	al, 20h	    ; space
  1456 00000991 AA                      	stosb
  1457 00000992 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1458 00000994 AA                      	stosb
  1459                                  	;
  1460 00000995 5A                      	pop	edx
  1461 00000996 59                      	pop	ecx
  1462                                  	;
  1463 00000997 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1464                                  			; white (F) forecolor
  1465 00000999 BE[14670000]            	mov	esi, exc_msg ; message offset
  1466                                  	;
  1467 0000099E EB11                    	jmp	short piemsg
  1468                                  	;
  1469                                          ;add    dword [scr_row], 0A0h
  1470                                          ;mov    edi, [scr_row]
  1471                                          ;
  1472                                  	;call 	printk
  1473                                  	;
  1474                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1475                                  	;out	20h, al	; 8259 PORT
  1476                                  	;
  1477                                  	;pop	es
  1478                                  	;pop	ds
  1479                                  	;pop	edi
  1480                                  	;pop	esi
  1481                                  	;pop 	eax
  1482                                  	;iret
  1483                                  	
  1484                                  	; 28/08/2015
  1485                                  	; 23/02/2015
  1486                                  	; 20/08/2014
  1487                                  ignore_int:
  1488 000009A0 50                      	push	eax
  1489 000009A1 53                      	push	ebx ; 23/02/2015
  1490 000009A2 56                      	push	esi
  1491 000009A3 57                      	push	edi
  1492 000009A4 1E                      	push 	ds
  1493 000009A5 06                      	push 	es
  1494                                  	; 28/08/2015
  1495 000009A6 0F20D8                  	mov	eax, cr3
  1496 000009A9 50                      	push	eax ; (*) page directory
  1497                                  	;
  1498 000009AA B467                    	mov	ah, 67h	; brown (6) background, 
  1499                                  			; light gray (7) forecolor
  1500 000009AC BE[D2660000]            	mov	esi, int_msg ; message offset
  1501                                  piemsg:
  1502                                          ; 27/08/2014
  1503 000009B1 8105[98660000]A000-             add     dword [scr_row], 0A0h
  1503 000009B9 0000               
  1504 000009BB 8B3D[98660000]                  mov     edi, [scr_row]
  1505                                          ;
  1506 000009C1 E8ACFCFFFF              	call 	printk
  1507                                  	;
  1508                                  	; 23/02/2015
  1509 000009C6 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1510 000009C8 E6A0                    	out	0A0h, al ; the 2nd 8259
  1511                                  iiretp: ; 01/09/2015
  1512                                  	; 28/08/2015
  1513 000009CA 58                      	pop	eax ; (*) page directory
  1514 000009CB 0F22D8                  	mov	cr3, eax
  1515                                  	;
  1516                                  iiret:
  1517                                  	; 22/08/2014
  1518 000009CE B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1519 000009D0 E620                    	out	20h, al	; 8259 PORT
  1520                                  	;
  1521 000009D2 07                      	pop	es
  1522 000009D3 1F                      	pop	ds
  1523 000009D4 5F                      	pop	edi
  1524 000009D5 5E                      	pop	esi
  1525 000009D6 5B                      	pop	ebx ; 29/08/2014
  1526 000009D7 58                      	pop 	eax
  1527 000009D8 CF                      	iretd
  1528                                  
  1529                                  	; 23/02/2022
  1530                                  	; 26/02/2015
  1531                                  	; 07/09/2014
  1532                                  	; 25/08/2014
  1533                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1534                                  	; 22/08/2014
  1535 000009D9 50                      	push	eax
  1536 000009DA 53                      	push	ebx ; 29/08/2014
  1537 000009DB 56                      	push	esi
  1538 000009DC 57                      	push	edi
  1539 000009DD 1E                      	push 	ds
  1540 000009DE 06                      	push 	es
  1541                                  	;
  1542 000009DF B810000000              	mov	eax, KDATA
  1543 000009E4 8ED8                    	mov	ds, ax
  1544 000009E6 8EC0                    	mov	es, ax
  1545                                  	;
  1546                                  	; 25/08/2014
  1547                                  	;call	rtc_p
  1548                                  	; 23/02/2022
  1549 000009E8 FF15[31070000]          	call	[x_rtci]
  1550                                  	;
  1551                                  	; 22/02/2015 - dsectpm.s
  1552                                  	; [ source: http://wiki.osdev.org/RTC ]
  1553                                  	; read status register C to complete procedure
  1554                                  	;(it is needed to get a next IRQ 8) 
  1555 000009EE B00C                    	mov	al, 0Ch ; 
  1556 000009F0 E670                    	out	70h, al ; select register C
  1557 000009F2 90                      	nop
  1558 000009F3 E471                    	in	al, 71h ; just throw away contents
  1559                                  	; 22/02/2015
  1560 000009F5 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1561 000009F7 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1562                                  	;
  1563 000009F9 EBD3                    	jmp	short iiret	
  1564                                  
  1565                                  	; 22/08/2014
  1566                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1567                                  	; (INT 1Ah)
  1568                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1569                                  time_of_day:
  1570 000009FB E86D010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1571 00000A00 726F                            jc      short rtc_retn 
  1572 00000A02 B000                    	mov	al, CMOS_SECONDS
  1573 00000A04 E84C010000              	call	CMOS_READ
  1574 00000A09 A2[BC6B0000]            	mov	[time_seconds], al 
  1575 00000A0E B002                    	mov	al, CMOS_MINUTES
  1576 00000A10 E840010000              	call	CMOS_READ
  1577 00000A15 A2[BD6B0000]            	mov	[time_minutes], al 
  1578 00000A1A B004                    	mov	al, CMOS_HOURS
  1579 00000A1C E834010000              	call	CMOS_READ
  1580 00000A21 A2[BE6B0000]                    mov     [time_hours], al
  1581 00000A26 B006                    	mov	al, CMOS_DAY_WEEK 
  1582 00000A28 E828010000              	call	CMOS_READ
  1583 00000A2D A2[BF6B0000]            	mov	[date_wday], al
  1584 00000A32 B007                     	mov	al, CMOS_DAY_MONTH
  1585 00000A34 E81C010000              	call	CMOS_READ
  1586 00000A39 A2[C06B0000]            	mov	[date_day], al
  1587 00000A3E B008                    	mov	al, CMOS_MONTH
  1588 00000A40 E810010000              	call	CMOS_READ
  1589 00000A45 A2[C16B0000]            	mov	[date_month], al
  1590 00000A4A B009                    	mov	al, CMOS_YEAR
  1591 00000A4C E804010000              	call	CMOS_READ
  1592 00000A51 A2[C26B0000]            	mov	[date_year], al
  1593 00000A56 B032                    	mov	al, CMOS_CENTURY
  1594 00000A58 E8F8000000              	call	CMOS_READ
  1595 00000A5D A2[C36B0000]            	mov	[date_century], al
  1596                                  	;
  1597 00000A62 B000                    	mov	al, CMOS_SECONDS
  1598 00000A64 E8EC000000              	call 	CMOS_READ
  1599 00000A69 3A05[BC6B0000]          	cmp	al, [time_seconds]
  1600 00000A6F 758A                    	jne	short time_of_day
  1601                                  
  1602                                  rtc_retn:
  1603 00000A71 C3                      	retn
  1604                                  
  1605                                  rtci_default:
  1606                                  	; 23/02/2022 (Temporary!)
  1607                                  	; (default real time clock handler in multitasking mode)
  1608                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1609 00000A72 FF05[C47F0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1610                                  			; (not used in anywhere of kernel for now!)
  1611 00000A78 C3                      	retn
  1612                                  
  1613                                  rtc_p:	
  1614                                  	; 12/02/2022
  1615                                  	; 07/09/2014
  1616                                  	; 29/08/2014
  1617                                  	; 27/08/2014
  1618                                  	; 25/08/2014
  1619                                   	; Print Real Time Clock content
  1620                                  	;
  1621                                  	;
  1622 00000A79 E87DFFFFFF              	call	time_of_day
  1623 00000A7E 72F1                    	jc	short rtc_retn
  1624                                  	;
  1625 00000A80 3A05[86670000]          	cmp	al, [ptime_seconds]
  1626 00000A86 74E9                            je      short rtc_retn ; 29/08/2014
  1627                                  	;
  1628 00000A88 A2[86670000]            	mov	[ptime_seconds], al
  1629                                  	;
  1630 00000A8D A0[C36B0000]            	mov	al, [date_century]
  1631 00000A92 E8F1000000              	call	bcd_to_ascii
  1632 00000A97 66A3[53670000]          	mov	[datestr+6], ax
  1633 00000A9D A0[C26B0000]            	mov	al, [date_year]
  1634 00000AA2 E8E1000000              	call	bcd_to_ascii
  1635 00000AA7 66A3[55670000]          	mov	[datestr+8], ax
  1636 00000AAD A0[C16B0000]            	mov	al, [date_month]
  1637 00000AB2 E8D1000000              	call	bcd_to_ascii
  1638 00000AB7 66A3[50670000]          	mov	[datestr+3], ax
  1639 00000ABD A0[C06B0000]            	mov	al, [date_day]
  1640 00000AC2 E8C1000000              	call	bcd_to_ascii
  1641 00000AC7 66A3[4D670000]          	mov	[datestr], ax
  1642                                  	;
  1643 00000ACD 0FB61D[BF6B0000]        	movzx	ebx, byte [date_wday]
  1644 00000AD4 C0E302                  	shl 	bl, 2
  1645 00000AD7 81C3[66670000]          	add	ebx, daytmp
  1646 00000ADD 8B03                    	mov	eax, [ebx]
  1647 00000ADF A3[58670000]            	mov	[daystr], eax
  1648                                  	;
  1649 00000AE4 A0[BE6B0000]            	mov	al, [time_hours]
  1650 00000AE9 E89A000000              	call	bcd_to_ascii
  1651 00000AEE 66A3[5C670000]          	mov	[timestr], ax
  1652 00000AF4 A0[BD6B0000]            	mov	al, [time_minutes]
  1653 00000AF9 E88A000000              	call	bcd_to_ascii
  1654 00000AFE 66A3[5F670000]          	mov	[timestr+3], ax
  1655 00000B04 A0[BC6B0000]            	mov	al, [time_seconds]
  1656 00000B09 E87A000000              	call	bcd_to_ascii
  1657 00000B0E 66A3[62670000]          	mov	[timestr+6], ax
  1658                                  	;		
  1659 00000B14 BE[3B670000]            	mov	esi, rtc_msg ; message offset
  1660                                  	; 23/02/2015
  1661 00000B19 52                      	push	edx
  1662 00000B1A 51                      	push	ecx
  1663                                  	; 07/09/2014
  1664                                  	;mov	bx, 2		; Video page 2
  1665                                  	; 12/02/2022
  1666 00000B1B 66BB0700                	mov	bx, 7		; Video page 7
  1667                                  prtmsg:
  1668 00000B1F AC                      	lodsb
  1669 00000B20 08C0                    	or	al, al
  1670 00000B22 740F                    	jz	short prtmsg_ok
  1671 00000B24 56                      	push	esi
  1672 00000B25 6653                    	push	bx
  1673 00000B27 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1674                                  			; white (F) forecolor
  1675 00000B29 E8C5080000              	call 	write_tty
  1676 00000B2E 665B                    	pop	bx
  1677 00000B30 5E                      	pop	esi
  1678 00000B31 EBEC                    	jmp	short prtmsg
  1679                                  	;
  1680                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1681                                  	;call	printk
  1682                                  prtmsg_ok:
  1683                                  	; 07/09/2014
  1684 00000B33 6631D2                  	xor	dx, dx		; column 0, row 0
  1685 00000B36 E8C2090000              	call	set_cpos	; set cursor position to 0,0 
  1686                                  	; 23/02/2015
  1687 00000B3B 59                      	pop	ecx
  1688 00000B3C 5A                      	pop	edx
  1689 00000B3D C3                      	retn
  1690                                  
  1691                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1692                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1693                                  default_irq7:
  1694 00000B3E 6650                    	push	ax
  1695 00000B40 B00B                    	mov	al, 0Bh  ; In-Service register
  1696 00000B42 E620                    	out	20h, al
  1697 00000B44 EB00                            jmp short $+2
  1698 00000B46 EB00                    	jmp short $+2
  1699 00000B48 E420                    	in	al, 20h
  1700 00000B4A 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1701 00000B4C 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1702 00000B4E B020                            mov     al, 20h ; EOI
  1703 00000B50 E620                    	out	20h, al 
  1704                                  irq7_iret:
  1705 00000B52 6658                    	pop	ax
  1706 00000B54 CF                      	iretd
  1707                                  	
  1708                                  	; 22/08/2014
  1709                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1710                                  CMOS_READ:
  1711 00000B55 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1712 00000B56 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1713 00000B58 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1714 00000B59 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1715 00000B5B FA                      	cli		; DISABLE INTERRUPTS
  1716 00000B5C E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1717 00000B5E 90                      	nop		; I/O DELAY
  1718 00000B5F E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1719 00000B61 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1720                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1721                                  		     ; ----- 10/06/85 (test4.asm)
  1722 00000B63 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1723                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1724 00000B65 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1725 00000B67 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1726 00000B69 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1727 00000B6B 9D                      	popf	
  1728 00000B6C C3                      	retn		; RETURN WITH FLAGS RESTORED
  1729                                  
  1730                                  	; 22/08/2014
  1731                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1732                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1733 00000B6D 51                      	push	ecx
  1734 00000B6E B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1735                                  		; mov cx, 800	
  1736                                  UPD_10:
  1737 00000B73 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1738 00000B75 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1739 00000B76 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1740 00000B7B A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1741 00000B7D 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1742 00000B7F FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1743 00000B80 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1744 00000B82 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1745                                  		; xor ax, ax
  1746 00000B84 F9                      	stc				; SET CARRY FOR ERROR
  1747                                  UPD_90:
  1748 00000B85 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1749 00000B86 FA                      	cli				; INTERRUPTS OFF DURING SET
  1750 00000B87 C3                      	retn				; RETURN WITH CY FLAG SET
  1751                                  
  1752                                  bcd_to_ascii:
  1753                                  	; 25/08/2014
  1754                                  	; INPUT ->
  1755                                  	;	al = Packed BCD number
  1756                                  	; OUTPUT ->
  1757                                  	;	ax  = ASCII word/number
  1758                                  	;
  1759                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1760                                  	;
  1761 00000B88 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1762                                  					; AH = AL / 10h
  1763                                  					; AL = AL MOD 10h
  1764 00000B8A 660D3030                	or ax,'00'                      ; Make it ASCII based
  1765                                  
  1766 00000B8E 86E0                            xchg ah, al 
  1767                                  	
  1768 00000B90 C3                      	retn	
  1769                                  	
  1770                                  %include 'keyboard.inc' ; 07/03/2015
  1771                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1772                              <1> ; Last Modification: 23/02/2022
  1773                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1774                              <1> ;
  1775                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1776                              <1> 
  1777                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1778                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1779                              <1> ; 30/06/2015
  1780                              <1> ; 11/03/2015
  1781                              <1> ; 28/02/2015
  1782                              <1> ; 25/02/2015
  1783                              <1> ; 20/02/2015
  1784                              <1> ; 18/02/2015
  1785                              <1> ; 03/12/2014
  1786                              <1> ; 07/09/2014
  1787                              <1> ; KEYBOARD INTERRUPT HANDLER
  1788                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1789                              <1> 
  1790                              <1> ;getch:
  1791                              <1> ;	; 18/02/2015
  1792                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1793                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1794                              <1> ;	; routine, later... (multi tasking ability)
  1795                              <1> ;	; 28/02/2015
  1796                              <1> ;	sti	; enable interrupts
  1797                              <1> ;	;
  1798                              <1> ;	;push	esi
  1799                              <1> ;	;push	ebx
  1800                              <1> ;	;xor	ebx, ebx
  1801                              <1> ;	;mov	bl, [ptty]  ; active_page
  1802                              <1> ;	;mov	esi, ebx
  1803                              <1> ;	;shl 	si, 1
  1804                              <1> ;	;add	esi, ttychr
  1805                              <1> ;getch_1:
  1806                              <1> ;	;mov	ax, [esi]
  1807                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1808                              <1> ;	and	ax, ax
  1809                              <1> ;	jz	short getch_2
  1810                              <1> ;	mov	word [ttychr], 0
  1811                              <1> ;	;mov	word [esi], 0
  1812                              <1> ;	;pop	ebx
  1813                              <1> ;	;pop	esi
  1814                              <1> ;	retn
  1815                              <1> ;getch_2:
  1816                              <1> ;	hlt	; not proper for multi tasking!
  1817                              <1> ;		; (temporary halt for now)
  1818                              <1> ;		; 'sleep' on tty 
  1819                              <1> ;		; will (must) be located here		
  1820                              <1> ;	nop
  1821                              <1> ;	jmp	short getch_1
  1822                              <1> 
  1823                              <1> keyb_int:
  1824                              <1> 	; 23/02/2022
  1825                              <1> 	; 30/06/2015
  1826                              <1> 	; 25/02/2015
  1827                              <1> 	; 20/02/2015
  1828                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1829                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1830                              <1> 	; 30/06/2014
  1831                              <1> 	; 10/05/2013	
  1832                              <1>       	; Retro Unix 8086 v1 feature only!
  1833                              <1> 	; 03/03/2014
  1834                              <1> 	
  1835 00000B91 1E                  <1> 	push	ds
  1836 00000B92 53                  <1> 	push	ebx
  1837 00000B93 50                  <1> 	push	eax
  1838                              <1> 	;
  1839                              <1> 	; 23/02/2022
  1840 00000B94 9C                  <1> 	pushfd
  1841 00000B95 0E                  <1> 	push	cs
  1842                              <1> 	;mov	ax, KDATA
  1843 00000B96 31C0                <1> 	xor	eax, eax
  1844 00000B98 B010                <1> 	mov	al, KDATA
  1845 00000B9A 8ED8                <1> 	mov	ds, ax
  1846                              <1> 	;
  1847                              <1> 	;pushfd
  1848                              <1> 	;push	cs
  1849 00000B9C E810020000          <1> 	call	kb_int   ; int_09h
  1850                              <1> 	;
  1851 00000BA1 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1852                              <1> 	;call	getc
  1853 00000BA3 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1854 00000BA8 744E                <1> 	jz	short keyb_int4
  1855                              <1> 	;
  1856 00000BAA B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1857                              <1> 	;call	getc
  1858 00000BAC E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1859                              <1> 	;
  1860                              <1> 	; 20/02/2015
  1861 00000BB1 0FB61D[766B0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1862                              <1> 	;
  1863 00000BB8 20C0                <1> 	and 	al, al
  1864 00000BBA 751D                <1> 	jnz	short keyb_int1
  1865                              <1> 	;
  1866 00000BBC 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1867 00000BBF 7218                <1> 	jb	short keyb_int1
  1868 00000BC1 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1869 00000BC4 7713                <1> 	ja	short keyb_int1
  1870                              <1> 	;
  1871 00000BC6 88D8                <1> 	mov	al, bl
  1872 00000BC8 0468                <1> 	add	al, 68h
  1873 00000BCA 38E0                <1> 	cmp	al, ah
  1874 00000BCC 7409                <1> 	je	short keyb_int0
  1875 00000BCE 88E0                <1> 	mov	al, ah
  1876 00000BD0 2C68                <1> 	sub	al, 68h
  1877 00000BD2 E83F0A0000          <1> 	call	tty_sw
  1878                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1879                              <1> keyb_int0: ; 30/06/2015
  1880                              <1> 	;xor	ax, ax
  1881                              <1> 	; 23/02/2022
  1882 00000BD7 31C0                <1> 	xor	eax, eax
  1883                              <1> keyb_int1:
  1884 00000BD9 D0E3                <1> 	shl	bl, 1
  1885 00000BDB 81C3[786B0000]      <1> 	add	ebx, ttychr
  1886                              <1> 	;
  1887                              <1> 	;23/02/2022
  1888 00000BE1 09C0                <1> 	or	eax, eax
  1889                              <1> 	;or	ax, ax
  1890 00000BE3 7406                <1> 	jz	short keyb_int2
  1891                              <1> 	;
  1892 00000BE5 66833B00            <1> 	cmp 	word [ebx], 0
  1893 00000BE9 7703                <1>         ja      short keyb_int3 
  1894                              <1> keyb_int2:
  1895 00000BEB 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1896                              <1> 			   ; and scan code of the character
  1897                              <1> 			   ; for current tty (or last tty
  1898                              <1> 			   ; just before tty switch).
  1899                              <1> keyb_int3:
  1900 00000BEE A0[766B0000]        <1>         mov     al, [ptty]
  1901 00000BF3 E8DE430000          <1> 	call	wakeup
  1902                              <1> 	;
  1903                              <1> keyb_int4:
  1904 00000BF8 58                  <1> 	pop	eax
  1905 00000BF9 5B                  <1> 	pop	ebx
  1906 00000BFA 1F                  <1> 	pop	ds
  1907 00000BFB CF                  <1> 	iret
  1908                              <1> 
  1909                              <1> ; 18/02/2015
  1910                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1911                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1912                              <1> ; scancode and ascii code of the character 
  1913                              <1> ; in the tty input (ttychr) buffer. 
  1914                              <1> ; Test procedures must call 'getch' for tty input
  1915                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1916                              <1> ; due to infinite (key press) waiting loop.
  1917                              <1> ; 
  1918                              <1> ; 03/12/2014
  1919                              <1> ; 26/08/2014
  1920                              <1> ; KEYBOARD I/O
  1921                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1922                              <1> 
  1923                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1924                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1925                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1926                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1927                              <1> 
  1928                              <1> int_16h: ; 30/06/2015
  1929                              <1> ;getc:
  1930 00000BFC 9C                  <1> 	pushfd	; 28/08/2014
  1931 00000BFD 0E                  <1> 	push 	cs
  1932 00000BFE E826000000          <1> 	call 	getc_int
  1933 00000C03 C3                  <1> 	retn
  1934                              <1> 
  1935                              <1> ; 24/12/2021
  1936                              <1> 
  1937                              <1> 	;-----	SHIFT STATUS
  1938                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  1939 00000C04 8A25[74650000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  1940 00000C0A 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  1941                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  1942                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  1943 00000C0D C0E405              <1>         shl	ah, 5
  1944 00000C10 A0[74650000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  1945 00000C15 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  1946 00000C17 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  1947 00000C19 A0[76650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  1948 00000C1E 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  1949 00000C20 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  1950                              <1> _K3:
  1951 00000C22 A0[73650000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  1952 00000C27 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  1953                              <1> 
  1954                              <1> getc_int:
  1955                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  1956                              <1> 	; 28/02/2015
  1957                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  1958                              <1> 	;	      instead of pc-at bios - 1985-)
  1959                              <1> 	; 28/08/2014 (_k1d)
  1960                              <1> 	; 30/06/2014
  1961                              <1> 	; 03/03/2014
  1962                              <1> 	; 28/02/2014
  1963                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  1964                              <1> 	; rombios source code (21/04/1986)
  1965                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  1966                              <1> 	;
  1967                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  1968                              <1> 	;
  1969                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  1970                              <1> 	; KEYBOARD I/O								      :
  1971                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  1972                              <1> 	; INPUT									      :
  1973                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  1974                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  1975                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  1976                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  1977                              <1> 	;-----------------------------------------------------------------------------:
  1978                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  1979                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  1980                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  1981                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  1982                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  1983                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  1984                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  1985                              <1> 	;-----------------------------------------------------------------------------:	
  1986                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  1987                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  1988                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  1989                              <1> 	;-----------------------------------------------------------------------------:	
  1990                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  1991                              <1> 	;	      (AL) = 05H                                                      :
  1992                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  1993                              <1> 	;		       							      :
  1994                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  1995                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  1996                              <1> 	;                     --------------------------------------------            :
  1997                              <1> 	;			00H        30.0        10H        7.5                 :
  1998                              <1> 	;			01H        26.7        11H        6.7                 :
  1999                              <1> 	;			02H        24.0        12H        6.0                 :
  2000                              <1> 	;			03H        21.8        13H        5.5                 :
  2001                              <1> 	;			04H        20.0        14H        5.0                 :
  2002                              <1> 	;			05H        18.5        15H        4.6                 :
  2003                              <1> 	;			06H        17.1        16H        4.3                 :
  2004                              <1> 	;			07H        16.0        17H        4.0                 :
  2005                              <1> 	;			08H        15.0        18H        3.7                 :
  2006                              <1> 	;			09H        13.3        19H        3.3                 :
  2007                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2008                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2009                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2010                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2011                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2012                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2013                              <1> 	;									      :
  2014                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2015                              <1> 	;		       							      :
  2016                              <1> 	;                     REGISTER     DELAY                                      :
  2017                              <1> 	;                      VALUE       VALUE                                      :
  2018                              <1> 	;                     ------------------                                      :
  2019                              <1> 	;			00H        250 ms                                     :
  2020                              <1> 	;			01H        500 ms                                     :
  2021                              <1> 	;			02H        750 ms                                     :
  2022                              <1> 	;			03H       1000 ms                                     :
  2023                              <1> 	;-----------------------------------------------------------------------------:
  2024                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2025                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2026                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2027                              <1> 	;		           (CH) = SCAN CODE                                   :
  2028                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2029                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2030                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2031                              <1> 	;-----------------------------------------------------------------------------:		
  2032                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2033                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2034                              <1> 	;-----------------------------------------------------------------------------:
  2035                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2036                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2037                              <1> 	;-----------------------------------------------------------------------------:	
  2038                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2039                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2040                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2041                              <1> 	; OUTPUT					                              :
  2042                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2043                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2044                              <1> 	;------------------------------------------------------------------------------
  2045                              <1> 	
  2046 00000C29 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2047 00000C2A 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2048 00000C2B 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2049                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2050 00000C2C 66BB1000            <1>         mov     bx, KDATA 
  2051 00000C30 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2052 00000C32 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2053 00000C34 742D                <1> 	jz	short _K1		; ASCII_READ
  2054 00000C36 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2055 00000C38 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2056 00000C3A FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2057 00000C3C 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2058 00000C3E FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2059 00000C40 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2060 00000C42 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2061 00000C45 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2062                              <1> _KIO1:	
  2063 00000C47 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2064 00000C4A 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2065 00000C4C FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2066 00000C4E 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2067 00000C50 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2068 00000C52 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2069                              <1> _KIO_EXIT:
  2070                              <1> 	;pop	ecx			; RECOVER REGISTER
  2071 00000C54 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2072 00000C55 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2073 00000C56 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2074                              <1> 
  2075                              <1> 	;-----	ASCII CHARACTER
  2076                              <1> _K1E:	
  2077 00000C57 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2078 00000C5C E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2079 00000C61 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2080                              <1> _K1:	
  2081 00000C63 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2082 00000C68 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2083 00000C6D 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2084                              <1> _K1A:
  2085 00000C6F EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2086                              <1> 
  2087                              <1> 	;-----	ASCII STATUS
  2088                              <1> _K2E:	
  2089 00000C71 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2090 00000C76 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2091 00000C78 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2092 00000C79 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2093 00000C7E EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2094                              <1> _K2:	
  2095 00000C80 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2096 00000C85 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2097 00000C87 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2098 00000C88 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2099 00000C8D 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2100 00000C8F 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2101 00000C90 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2102 00000C95 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2103                              <1> _K2A:
  2104 00000C97 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2105                              <1> _K2B:
  2106                              <1> 	;pop	ecx			; RECOVER REGISTER
  2107 00000C98 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2108 00000C99 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2109 00000C9A CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2110                              <1> 
  2111                              <1> ; 24/12/2021
  2112                              <1> ;	;-----	SHIFT STATUS
  2113                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2114                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2115                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2116                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2117                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2118                              <1> ;       shl	ah, 5
  2119                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2120                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2121                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2122                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2123                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2124                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2125                              <1> ;_K3:
  2126                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2127                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2128                              <1> 
  2129                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2130                              <1> _K300:
  2131 00000C9D 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2132 00000C9F 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2133 00000CA1 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2134 00000CA4 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2135 00000CA6 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2136 00000CA9 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2137 00000CAB B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2138 00000CAD E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2139                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2140                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2141 00000CB2 C0E705              <1> 	shl	bh, 5
  2142 00000CB5 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2143 00000CB7 08F8                <1> 	or	al, bh			; AND DELAY
  2144 00000CB9 E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2145 00000CBE EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2146                              <1> 
  2147                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2148                              <1> _K500:
  2149 00000CC0 56                  <1> 	push	esi			; SAVE SI (esi)
  2150 00000CC1 FA                  <1> 	cli				; 
  2151 00000CC2 8B1D[84650000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2152 00000CC8 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2153 00000CCA E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2154 00000CCF 3B1D[80650000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2155 00000CD5 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2156 00000CD7 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2157 00000CDA 891D[84650000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2158 00000CE0 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2159 00000CE2 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2160                              <1> _K502:
  2161 00000CE4 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2162                              <1> _K504:
  2163 00000CE6 FB                  <1> 	sti				
  2164 00000CE7 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2165 00000CE8 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2166                              <1> 
  2167                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2168                              <1> _K1S:
  2169 00000CED FA                  <1> 	cli	; 03/12/2014
  2170 00000CEE 8B1D[80650000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2171 00000CF4 3B1D[84650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2172                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2173 00000CFA 750F                <1> 	jne	short _k1x ; 03/12/2014
  2174                              <1> 	;
  2175                              <1> 	; 03/12/2014
  2176                              <1> 	; 28/08/2014
  2177                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2178                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2179                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2180                              <1> _K1T:                                   ; ASCII READ
  2181 00000CFC FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2182 00000CFD 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2183                              <1> _K1U:	
  2184 00000CFE FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2185 00000CFF 8B1D[80650000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2186 00000D05 3B1D[84650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2187                              <1> _k1x:
  2188 00000D0B 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2189 00000D0C 9C                  <1> 	pushf				; SAVE FLAGS
  2190 00000D0D E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2191 00000D12 8A1D[75650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2192 00000D18 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2193 00000D1A 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2194 00000D1D 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2195 00000D1F E86E060000          <1> 	call	SND_LED1
  2196 00000D24 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2197                              <1> _K1V:
  2198 00000D25 9D                  <1> 	popf				; RESTORE FLAGS
  2199 00000D26 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2200 00000D27 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2201                              <1> 	;
  2202 00000D29 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2203 00000D2C E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2204 00000D31 891D[80650000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2205 00000D37 C3                  <1> 	retn				; RETURN
  2206                              <1> 
  2207                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2208                              <1> _K2S:
  2209 00000D38 FA                  <1> 	cli				; INTERRUPTS OFF
  2210 00000D39 8B1D[80650000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2211 00000D3F 3B1D[84650000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2212 00000D45 668B03              <1> 	mov	ax, [ebx]
  2213 00000D48 9C                  <1> 	pushf				; SAVE FLAGS
  2214                              <1> 	;push	ax			; SAVE CODE
  2215                              <1> 	; 24/12/2021
  2216 00000D49 50                  <1> 	push	eax
  2217 00000D4A E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2218 00000D4F 8A1D[75650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2219 00000D55 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2220 00000D57 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2221 00000D5A 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2222 00000D5C E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2223                              <1> _K2T:
  2224                              <1> 	;pop	ax			; RESTORE CODE
  2225                              <1> 	; 24/12/2021
  2226 00000D61 58                  <1> 	pop	eax
  2227 00000D62 9D                  <1> 	popf				; RESTORE FLAGS
  2228 00000D63 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2229 00000D64 C3                  <1> 	retn				; RETURN
  2230                              <1> 
  2231                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2232                              <1> _KIO_E_XLAT:
  2233 00000D65 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2234 00000D67 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2235 00000D69 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2236 00000D6B 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2237 00000D6D 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2238                              <1> _KIO_E_RET:				
  2239 00000D6F C3                  <1> 	retn				; GO BACK
  2240                              <1> 
  2241                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2242                              <1> _KIO_S_XLAT:
  2243 00000D70 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2244 00000D73 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2245 00000D75 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2246 00000D77 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2247 00000D79 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2248 00000D7B 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2249 00000D7D B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2250                              <1> _kio_ret: ; 03/12/2014
  2251 00000D7F F8                  <1> 	clc
  2252 00000D80 C3                  <1> 	retn
  2253                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2254                              <1> _KIO_S1:				
  2255 00000D81 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2256                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2257 00000D83 C3                  <1> 	retn
  2258                              <1> _KIO_S2:		
  2259 00000D84 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2260 00000D87 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2261 00000D89 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2262 00000D8B 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2263 00000D8D 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2264 00000D8F 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2265 00000D91 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2266                              <1> _KIO_S3:
  2267 00000D93 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2268                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2269 00000D95 75E8                <1> 	jne	short _kio_ret
  2270 00000D97 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2271 00000D99 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2272 00000D9B 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2273                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2274                              <1> _KIO_USE:
  2275                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2276 00000D9D C3                  <1> 	retn				; RETURN	
  2277                              <1> _KIO_DIS:
  2278 00000D9E F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2279 00000D9F C3                  <1> 	retn				; RETURN
  2280                              <1> 
  2281                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2282                              <1> _K4:    
  2283 00000DA0 43                  <1> 	inc     ebx
  2284 00000DA1 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2285 00000DA2 3B1D[7C650000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2286                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2287 00000DA8 7206                <1> 	jb	short _K5
  2288 00000DAA 8B1D[78650000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2289                              <1> _K5:
  2290 00000DB0 C3                  <1> 	retn
  2291                              <1> 
  2292                              <1> ; 20/02/2015
  2293                              <1> ; 05/12/2014
  2294                              <1> ; 26/08/2014
  2295                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2296                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2297                              <1> ;
  2298                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2299                              <1> ; rombios source code (06/10/1985)
  2300                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2301                              <1> 
  2302                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2303                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2304                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2305                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2306                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2307                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2308                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2309                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2310                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2311                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2312                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2313                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2314                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2315                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2316                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2317                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2318                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2319                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2320                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2321                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2322                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2323                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2324                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2325                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2326                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2327                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2328                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2329                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2330                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2331                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2332                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2333                              <1> F11_M		equ	87		; F11 KEY MAKE
  2334                              <1> F12_M		equ	88		; F12 KEY MAKE
  2335                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2336                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2337                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2338                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2339                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2340                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2341                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2342                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2343                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2344                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2345                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2346                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2347                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2348                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2349                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2350                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2351                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2352                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2353                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2354                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2355                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2356                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2357                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2358                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2359                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2360                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2361                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2362                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2363                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2364                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2365                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2366                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2367                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2368                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2369                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2370                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2371                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2372                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2373                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2374                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2375                              <1> ;
  2376                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2377                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2378                              <1> INTA00		equ	020h		; 8259 PORT
  2379                              <1> 
  2380                              <1> 
  2381                              <1> kb_int:
  2382                              <1> 
  2383                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2384                              <1> ; 17/10/2015 ('ctrlbrk') 
  2385                              <1> ; 05/12/2014
  2386                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2387                              <1> 	;	      instead of pc-at bios - 1985-)
  2388                              <1> ; 26/08/2014
  2389                              <1> ;
  2390                              <1> ; 03/06/86  KEYBOARD BIOS
  2391                              <1> ;
  2392                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2393                              <1> ;										;
  2394                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2395                              <1> ;										;
  2396                              <1> ;--------------------------------------------------------------------------------
  2397                              <1> 
  2398                              <1> KB_INT_1:
  2399 00000DB1 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2400                              <1> 	;push	ebp
  2401 00000DB2 50                  <1> 	push	eax
  2402 00000DB3 53                  <1> 	push	ebx
  2403 00000DB4 51                  <1> 	push	ecx
  2404 00000DB5 52                  <1> 	push	edx
  2405 00000DB6 56                  <1> 	push	esi
  2406 00000DB7 57                  <1> 	push	edi
  2407 00000DB8 1E                  <1> 	push	ds
  2408 00000DB9 06                  <1> 	push	es
  2409 00000DBA FC                  <1> 	cld				; FORWARD DIRECTION
  2410 00000DBB 66B81000            <1> 	mov	ax, KDATA
  2411 00000DBF 8ED8                <1> 	mov	ds, ax
  2412 00000DC1 8EC0                <1> 	mov	es, ax
  2413                              <1> 	;
  2414                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2415 00000DC3 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2416 00000DC5 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2417 00000DCA FA                  <1> 	cli				; DISABLE INTERRUPTS
  2418 00000DCB B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2419                              <1> KB_INT_01:
  2420 00000DD0 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2421 00000DD2 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2422 00000DD4 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2423                              <1> 	;
  2424                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2425 00000DD6 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2426                              <1> 	;
  2427                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2428                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2429                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2430                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2431                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2432                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2433                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2434                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2435                              <1> 	;
  2436                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2437                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2438 00000DD8 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2439 00000DD9 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2440 00000DDB 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2441                              <1> 	;
  2442                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2443 00000DDD 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2444 00000DDF 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2445                              <1> 	;
  2446                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2447 00000DE1 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2448 00000DE2 800D[75650000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2449 00000DE9 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2450                              <1> 	;
  2451                              <1> 	;-----	RESEND THE LAST BYTE
  2452                              <1> KB_INT_4:
  2453 00000DEE FA                  <1> 	cli				; DISABLE INTERRUPTS
  2454 00000DEF 800D[75650000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2455 00000DF6 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2456                              <1> 	;
  2457                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2458                              <1> KB_INT_2:
  2459                              <1> 	;push 	ax			; SAVE DATA IN
  2460                              <1> 	; 24/12/2021
  2461 00000DFB 50                  <1> 	push	eax
  2462 00000DFC E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2463 00000E01 8A1D[75650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2464 00000E07 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2465 00000E09 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2466 00000E0C 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2467 00000E0E E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2468                              <1> UP0:
  2469                              <1> 	;pop	ax			; RESTORE DATA IN
  2470                              <1> 	; 24/12/2021
  2471 00000E13 58                  <1> 	pop	eax
  2472                              <1> ;------------------------------------------------------------------------
  2473                              <1> ;	START OF KEY PROCESSING						;
  2474                              <1> ;------------------------------------------------------------------------
  2475 00000E14 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2476                              <1> 	;
  2477                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2478 00000E16 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2479                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2480                              <1> 	; 24/12/2021
  2481 00000E18 7505                <1> 	jne	short K16
  2482 00000E1A E9ED040000          <1> 	jmp	K62
  2483                              <1> K16:	
  2484 00000E1F 8A3D[76650000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2485                              <1> 	;
  2486                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2487 00000E25 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2488 00000E28 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2489 00000E2A 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2490 00000E2C 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2491 00000E2E 7507                <1> 	jne	short RST_RD_ID
  2492 00000E30 800D[76650000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2493                              <1> RST_RD_ID:
  2494 00000E37 8025[76650000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2495 00000E3E EB27                <1>         jmp    short ID_EX		; AND EXIT
  2496                              <1> 	; 24/12/2021
  2497                              <1> 	;jmp	K26
  2498                              <1> 	;
  2499                              <1> TST_ID_2:
  2500 00000E40 8025[76650000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2501 00000E47 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2502 00000E49 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2503 00000E4B 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2504 00000E4D 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2505                              <1> 	; 24/12/2021
  2506                              <1> 	;jne	K26
  2507                              <1> 	;
  2508                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2509 00000E4F F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2510 00000E52 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2511 00000E54 800D[73650000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2512 00000E5B E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2513                              <1> KX_BIT:
  2514 00000E60 800D[76650000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2515 00000E67 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2516                              <1> 	;
  2517                              <1> NOT_ID:
  2518 00000E6C 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2519 00000E6E 750E                <1> 	jne	short TEST_E1
  2520 00000E70 800D[76650000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2521 00000E77 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2522                              <1> 	; 24/12/2021
  2523 00000E79 E9DA010000          <1> 	jmp	K26A	
  2524                              <1> TEST_E1:	
  2525 00000E7E 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2526 00000E80 750C                <1> 	jne	short NOT_HC
  2527 00000E82 800D[76650000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2528 00000E89 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2529                              <1> 	;
  2530                              <1> NOT_HC:
  2531 00000E8E 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2532 00000E90 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2533 00000E93 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2534                              <1> 	;
  2535 00000E95 BF[5E640000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2536 00000E9A AE                  <1> 	scasb
  2537                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2538                              <1> 	; 24/12/2021
  2539 00000E9B 7458                <1> 	je	short K16B
  2540 00000E9D AE                  <1> 	scasb
  2541 00000E9E 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2542 00000EA0 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2543                              <1> 	; 24/12/2021
  2544                              <1> 	;jmp	K26
  2545                              <1> 	;
  2546                              <1> NOT_LC_E0:
  2547 00000EA2 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2548 00000EA5 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2549 00000EA7 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2550 00000EAC BF[5C640000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2551 00000EB1 F2AE                <1> 	repne	scasb			; CHECK IT
  2552 00000EB3 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2553                              <1> 	; 24/12/2021
  2554                              <1> 	;je	K26A			
  2555                              <1> 	;
  2556 00000EB5 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2557 00000EB7 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2558                              <1> 	; 24/12/2021
  2559                              <1> 	;jne	K26
  2560 00000EB9 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2561 00000EBC 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2562                              <1> 	; 24/12/2021
  2563                              <1> 	;jnz	K26
  2564                              <1>         ; 20/02/2015 
  2565 00000EBE F605[74650000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2566 00000EC5 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2567                              <1> 	; 24/12/2021
  2568                              <1> 	;jnz	K26
  2569 00000EC7 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2570                              <1> 	;
  2571                              <1> 	;-----	TEST FOR SYSTEM KEY
  2572                              <1> T_SYS_KEY:
  2573 00000ECC 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2574 00000ECE 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2575                              <1> 	;
  2576 00000ED0 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2577 00000ED3 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2578                              <1> 	;
  2579 00000ED5 F605[74650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2580 00000EDC 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2581                              <1> 	;jnz	K26			
  2582                              <1> 	;
  2583 00000EDE 800D[74650000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2584 00000EE5 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2585 00000EE7 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2586                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2587 00000EE9 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2588 00000EEB E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2589                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2590                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2591                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2592                              <1> 	;INT	15H			; USER INTERRUPT	
  2593 00000EF0 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2594                              <1> 	;
  2595 00000EF5 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2596                              <1> 	;
  2597                              <1> K16C:
  2598 00000EFA 8025[74650000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2599 00000F01 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2600 00000F03 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2601                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2602                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2603                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2604                              <1> 	;
  2605                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2606                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2607                              <1> 	;INT	15H			; USER INTERRUPT
  2608                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2609                              <1> 	;
  2610 00000F05 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2611                              <1> 	;
  2612                              <1> 	;-----	TEST FOR SHIFT KEYS
  2613                              <1> K16A:
  2614 00000F0A 8A1D[73650000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2615 00000F10 BF[58640000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2616 00000F15 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2617 00000F1A F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2618 00000F1C 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2619                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2620                              <1> 	; 24/12/2021
  2621 00000F1E 7405                <1> 	je	short K17
  2622 00000F20 E914010000          <1> 	jmp	K25
  2623                              <1> 	;
  2624                              <1> 	;------	SHIFT KEY FOUND
  2625                              <1> K17:
  2626 00000F25 81EF[59640000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2627 00000F2B 8AA7[60640000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2628 00000F31 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2629 00000F33 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2630                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2631                              <1> 	; 24/12/2021
  2632 00000F35 7405                <1> 	jz	short K17C
  2633 00000F37 E999000000          <1> 	jmp	K23
  2634                              <1> 	;
  2635                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2636                              <1> K17C:
  2637 00000F3C 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2638 00000F3F 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2639                              <1> 	;
  2640                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2641 00000F41 0825[73650000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2642 00000F47 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2643 00000F49 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2644                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2645                              <1> 	; 24/12/2021
  2646 00000F4B E901010000          <1> 	jmp	K26
  2647                              <1> K17D:
  2648 00000F50 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2649 00000F53 740B                <1> 	jz 	short K17E		; NO, JUMP
  2650 00000F55 0825[76650000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2651 00000F5B E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2652                              <1> K17E:
  2653 00000F60 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2654 00000F62 0825[74650000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2655 00000F68 E9E4000000          <1> 	jmp	K26
  2656                              <1> 	;
  2657                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2658                              <1> K18:					; SHIFT-TOGGLE
  2659 00000F6D F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2660 00000F70 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2661                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2662                              <1> 	; 24/12/2021
  2663 00000F72 E9C2000000          <1> 	jmp	K25
  2664                              <1> K18A:
  2665 00000F77 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2666 00000F79 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2667 00000F7B F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2668 00000F7E 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2669                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2670                              <1> 	; 24/12/2021
  2671 00000F80 E9B4000000          <1> 	jmp	K25
  2672                              <1> K18B:
  2673 00000F85 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2674 00000F88 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2675                              <1> K19:	
  2676 00000F8A F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2677 00000F8D 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2678 00000F8F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2679 00000F92 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2680                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2681 00000F94 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2682 00000F96 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2683                              <1> K21:					; MIGHT BE NUMERIC
  2684 00000F9B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2685 00000F9E 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2686                              <1> 	;
  2687                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2688 00000FA0 8425[74650000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2689                              <1> 	;jnz	K26
  2690                              <1> 	; 24/12/2021
  2691 00000FA6 7405                <1> 	jz	short K22A
  2692 00000FA8 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2693                              <1> K22A:
  2694 00000FAD 0825[74650000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2695 00000FB3 3025[73650000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2696                              <1> 	;
  2697                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2698 00000FB9 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2699 00000FBC 7407                <1> 	jz	short K22B		; GO IF NOT
  2700                              <1> 	;
  2701                              <1> 	; 24/12/2021
  2702                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2703 00000FBE 50                  <1> 	push	eax
  2704 00000FBF E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2705                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2706 00000FC4 58                  <1> 	pop	eax
  2707                              <1> K22B:
  2708 00000FC5 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2709                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2710                              <1> 	; 24/12/2021
  2711 00000FC7 7405                <1> 	je	short K22C
  2712 00000FC9 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2713                              <1> K22C:
  2714 00000FCE 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2715 00000FD0 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2716                              <1> 	;
  2717                              <1> 	;-----	BREAK SHIFT FOUND
  2718                              <1> K23:					; BREAK-SHIFT-FOUND
  2719 00000FD5 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2720 00000FD8 F6D4                <1> 	not	ah			; INVERT MASK
  2721 00000FDA 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2722 00000FDC 2025[73650000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2723 00000FE2 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2724 00000FE5 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2725                              <1> 	;
  2726 00000FE7 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2727 00000FEA 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2728 00000FEC 2025[76650000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2729 00000FF2 EB08                <1> 	jmp	short K23B		; CONTINUE
  2730                              <1> K23A:
  2731 00000FF4 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2732 00000FF6 2025[74650000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2733                              <1> K23B:
  2734 00000FFC 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2735 00000FFE A0[76650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2736 00001003 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2737 00001005 0A05[74650000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2738 0000100B D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2739 0000100D 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2740 0000100F 0805[73650000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2741 00001015 88E0                <1> 	mov	al, ah
  2742                              <1> K23D:
  2743 00001017 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2744 00001019 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2745                              <1> 	;	
  2746                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2747 0000101B A0[77650000]        <1> 	mov	al, [ALT_INPUT]
  2748 00001020 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2749 00001022 8825[77650000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2750 00001028 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2751 0000102A 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2752 0000102C E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2753                              <1> 	;
  2754                              <1> K24:					; BREAK-TOGGLE
  2755 00001031 2025[74650000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2756 00001037 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2757                              <1> 	;
  2758                              <1> 	;-----	TEST FOR HOLD STATE
  2759                              <1> 					; AL, AH = SCAN CODE
  2760                              <1> K25:					; NO-SHIFT-FOUND
  2761 00001039 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2762 0000103B 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2763 0000103D F605[74650000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2764 00001044 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2765 00001046 3C45                <1> 	cmp	al, NUM_KEY
  2766 00001048 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2767 0000104A 8025[74650000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2768                              <1> 	;
  2769                              <1> K26:
  2770 00001051 8025[76650000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2771                              <1> K26A:					; INTERRUPT-RETURN
  2772 00001058 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2773 00001059 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2774 0000105B E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2775                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2776 0000105D B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2777 0000105F E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2778                              <1> K27A:
  2779 00001064 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2780 00001065 07                  <1> 	pop	es			; RESTORE REGISTERS
  2781 00001066 1F                  <1> 	pop	ds
  2782 00001067 5F                  <1> 	pop	edi
  2783 00001068 5E                  <1> 	pop	esi
  2784 00001069 5A                  <1> 	pop	edx
  2785 0000106A 59                  <1> 	pop	ecx
  2786 0000106B 5B                  <1> 	pop	ebx
  2787 0000106C 58                  <1> 	pop	eax
  2788                              <1> 	;pop	ebp
  2789 0000106D CF                  <1> 	iret				; RETURN
  2790                              <1> 
  2791                              <1> 	;-----	NOT IN	HOLD STATE
  2792                              <1> K28:					; NO-HOLD-STATE
  2793 0000106E 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2794 00001070 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2795                              <1> 	;
  2796 00001072 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2797 00001075 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2798                              <1>         ; 24/12/2021
  2799                              <1> 	;jz      K38
  2800                              <1> 	;
  2801 00001077 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2802 0000107A 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2803                              <1> 	; 28/02/2015
  2804 0000107C F605[74650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2805 00001083 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2806                              <1> 	; 24/12/2021
  2807                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2808                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2809 00001085 E9D1000000          <1> K28A:	jmp	K38
  2810                              <1> 	;
  2811                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2812                              <1> K29:					; TEST-RESET
  2813 0000108A F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2814 0000108D 740B                <1> 	jz	short K31		; NO_RESET
  2815 0000108F 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2816 00001091 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2817                              <1> 	;
  2818                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2819                              <1>  	; 26/08/2014
  2820                              <1> cpu_reset:
  2821                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2822                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2823 00001093 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2824 00001095 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2825                              <1> khere:
  2826 00001097 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2827 00001098 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2828                              <1> 
  2829                              <1> 	;
  2830                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2831                              <1> K31:					; NO-RESET
  2832 0000109A 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2833 0000109C 7507                <1> 	jne	short K311		; NOT THERE
  2834 0000109E B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2835 000010A0 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2836                              <1> K311:
  2837 000010A5 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2838 000010A7 7509                <1> 	jne	short K312		; NOT THERE
  2839 000010A9 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2840 000010AD E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2841                              <1> K312:
  2842 000010B2 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2843 000010B4 7471                <1>         je	short K37B              ; GO PROCESS
  2844 000010B6 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2845 000010B8 746D                <1>         je	short K37B              ; GO PROCESS
  2846                              <1> 	;
  2847                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2848                              <1> K32:					; ALT-KEY-PAD
  2849 000010BA BF[34640000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2850 000010BF B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2851 000010C4 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2852 000010C6 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2853 000010C8 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2854                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2855                              <1> 	; 24/12/2021
  2856 000010CB 751C                <1> 	jnz	short K32B
  2857 000010CD 81EF[35640000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2858 000010D3 A0[77650000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2859 000010D8 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2860 000010DA F6E4                <1> 	mul	ah
  2861 000010DC 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2862 000010DF A2[77650000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2863                              <1> K32A:
  2864 000010E4 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2865                              <1> K32B:
  2866                              <1> 	; 24/12/2021
  2867 000010E9 EB6A                <1> 	jmp	K37C
  2868                              <1> 	;
  2869                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2870                              <1> K33:					; NO-ALT-KEYPAD
  2871 000010EB C605[77650000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2872 000010F2 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2873 000010F7 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2874 000010F9 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2875                              <1> 	;
  2876                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2877                              <1> K34:					; ALT-TOP-ROW
  2878 000010FB 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2879 000010FD 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2880 000010FF 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2881 00001101 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2882 00001103 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2883 00001106 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2884                              <1> 	;
  2885                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2886                              <1> K35:					; ALT-FUNCTION
  2887 00001108 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2888 0000110A 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2889 0000110C 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2890 0000110E 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2891 00001110 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2892 00001113 EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2893                              <1> K35A:
  2894 00001115 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2895 00001118 7425                <1> 	jz	short K37		; NO, JUMP
  2896 0000111A 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2897 0000111C 7510                <1>         jne     short K35B              ; NOT THERE
  2898 0000111E 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2899 00001122 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2900                              <1> K37B:
  2901 00001127 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2902 00001129 E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2903                              <1> K35B:
  2904 0000112E 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2905 00001130 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2906 00001132 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2907 00001134 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2908                              <1>         ; 24/12/2021
  2909                              <1> 	;jne	K26
  2910 00001136 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2911 0000113A E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2912                              <1> K37:
  2913 0000113F 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2914 00001141 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2915 00001143 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2916                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2917 00001145 0F8706FFFFFF        <1>         ja      K26
  2918 0000114B 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2919                              <1> K37A:
  2920 0000114E B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2921 00001150 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2922                              <1> K37C:
  2923 00001155 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2924 00001157 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2925 00001159 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2926                              <1> 	;
  2927                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2928                              <1> K38:					; NOT-ALT-SHIFT
  2929                              <1> 					; BL STILL HAS SHIFT FLAGS
  2930 0000115B F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2931 0000115E 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2932                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2933                              <1> 	; 24/12/2021
  2934 00001160 E9AB000000          <1> 	jmp	K44
  2935                              <1> 	;
  2936                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  2937                              <1> 	;-----	TEST FOR BREAK
  2938                              <1> K38A:
  2939 00001165 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  2940 00001167 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  2941 00001169 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2942 0000116C 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  2943 0000116E F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  2944 00001171 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  2945                              <1> K38B:
  2946 00001173 8B1D[80650000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  2947 00001179 891D[84650000]      <1> 	mov	[BUFFER_TAIL], ebx
  2948 0000117F C605[72650000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  2949                              <1> 	;
  2950                              <1> 	;-----	ENABLE KEYBOARD
  2951 00001186 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  2952 00001188 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2953                              <1> 	;
  2954                              <1> 	; CTRL+BREAK code here !!!
  2955                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  2956                              <1> 	; 17/10/2015	
  2957 0000118D E879220000          <1> 	call	ctrlbrk ; control+break subroutine
  2958                              <1> 	;
  2959                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  2960                              <1> 	; 24/12/2021
  2961 00001192 29C0                <1> 	sub	eax, eax
  2962 00001194 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  2963                              <1> 	;
  2964                              <1> 	;-----	TEST FOR PAUSE
  2965                              <1> K39:					; NO_BREAK
  2966 00001199 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2967 0000119C 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  2968 0000119E 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  2969 000011A0 7533                <1> 	jne	short K41		; NO-PAUSE
  2970                              <1> K39P:
  2971 000011A2 800D[74650000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  2972                              <1> 	;
  2973                              <1> 	;-----	ENABLE KEYBOARD
  2974 000011A9 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  2975 000011AB E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2976                              <1> K39A:
  2977 000011B0 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  2978 000011B2 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  2979                              <1> 	;
  2980                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  2981 000011B4 803D[70650000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  2982 000011BB 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  2983 000011BD 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  2984 000011C1 A0[71650000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  2985 000011C6 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  2986                              <1> 	;
  2987                              <1> K40:					; PAUSE-LOOP
  2988 000011C7 F605[74650000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  2989 000011CE 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  2990                              <1> 	;
  2991 000011D0 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  2992                              <1>         ;
  2993                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  2994                              <1> K41:					; NO-PAUSE
  2995 000011D5 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  2996 000011D7 7513                <1> 	jne	short K42		; NOT-KEY-55
  2997 000011D9 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2998 000011DC 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  2999 000011DE F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3000 000011E1 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3001                              <1> K41A:	
  3002 000011E3 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3003 000011E7 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3004                              <1> 	;
  3005                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3006                              <1> K42:					; NOT-KEY-55
  3007 000011EC 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3008 000011EE 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3009 000011F0 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3010 000011F2 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3011 000011F4 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3012 000011F7 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3013 000011F9 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3014 000011FD E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3015                              <1> K42A:
  3016                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3017 00001202 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3018                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3019                              <1> 	;;jb	K56 ; 20/02/2015
  3020                              <1> 	;;jmp	K64 ; 20/02/2015
  3021                              <1> K42B:
  3022 00001204 BB[68640000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3023                              <1> 	;;jmp	K64
  3024                              <1> 	;jb	K56 ;; 20/02/2015	
  3025                              <1> 	; 24/12/2021
  3026 00001209 7267                <1> 	jb	short K45F
  3027 0000120B E9B9000000          <1> 	jmp	K64	
  3028                              <1>         ;
  3029                              <1> 	;-----	NOT IN CONTROL SHIFT
  3030                              <1> K44:					; NOT-CTL-SHIFT
  3031 00001210 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3032 00001212 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3033 00001214 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3034 00001217 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3035 00001219 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3036 0000121C 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3037 0000121E EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3038                              <1> K44A:
  3039 00001220 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3040 00001223 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3041                              <1> 	;
  3042                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3043                              <1> K44B:
  3044 00001225 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3045 00001227 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3046 0000122C B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3047 0000122E E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3048                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3049                              <1> 	;PUSH 	BP			; SAVE POINTER
  3050                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3051                              <1> 	;POP	BP			; RESTORE POINTER
  3052 00001230 8025[76650000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3053 00001237 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3054                              <1> 	;
  3055                              <1> 	;-----	HANDLE IN-CORE KEYS
  3056                              <1> K45:					; NOT-PRINT-SCREEN
  3057 0000123C 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3058 0000123E 7734                <1> 	ja	short K46		; JUMP IF NOT
  3059 00001240 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3060 00001242 7505                <1> 	jne	short K45A		; NO, JUMP
  3061 00001244 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3062 00001247 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3063                              <1> K45A:
  3064 00001249 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3065 0000124E BF[3E640000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3066 00001253 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3067                              <1> 		; 20/02/2015
  3068 00001255 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3069                              <1> 	;
  3070 00001257 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3071 0000125A 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3072                              <1> K45B:
  3073 0000125C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3074 0000125F 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3075                              <1> 					; NO, LOWERCASE
  3076                              <1> K45C:
  3077 00001261 BB[C0640000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3078 00001266 EB51                <1> 	jmp	short K56	
  3079                              <1> K45D:					; ALMOST-CAPS-STATE
  3080 00001268 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3081 0000126B 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3082                              <1> K45E:
  3083 0000126D BB[18650000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3084 00001272 EB45                <1> K45F:	jmp	short K56
  3085                              <1> 	;
  3086                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3087                              <1> K46:					; NOT IN-CORE AREA
  3088 00001274 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3089                              <1> 	;ja	short K47		; JUMP IF NOT
  3090                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3091 00001276 7635                <1> 	jna	short K53		
  3092                              <1> 	;
  3093                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3094                              <1> K47:					; NOT F1 - F10
  3095 00001278 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3096 0000127A 772D                <1> 	ja	short K52		; JUMP IF NOT
  3097                              <1> 	;
  3098                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3099                              <1> K48:
  3100 0000127C 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3101 0000127E 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3102 00001280 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3103 00001282 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3104 00001284 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3105 00001287 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3106                              <1> 	;		
  3107 00001289 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3108 0000128C 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3109 0000128E F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3110                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3111 00001291 75DA                <1> 	jnz	short K45E
  3112                              <1> 	;
  3113                              <1> 	;-----	BASE CASE FOR KEYPAD
  3114                              <1> K49:					
  3115 00001293 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3116 00001295 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3117 00001297 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3118 00001299 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3119                              <1> K49A:
  3120 0000129B BB[C0640000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3121 000012A0 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3122                              <1> 	;
  3123                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3124                              <1> K50:					; ALMOST-NUM-STATE
  3125 000012A2 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3126 000012A5 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3127 000012A7 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3128                              <1> 	;
  3129                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3130                              <1> K52:					; NOT A NUMPAD KEY
  3131 000012A9 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3132                              <1> 	;jne	short K53		; JUMP IF NOT
  3133                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3134 000012AB 74AF                <1> 	je	short K45B		
  3135                              <1> 	;
  3136                              <1> 	;-----	MUST BE F11 OR F12 
  3137                              <1> K53:					; F1 - F10 COME HERE, TOO
  3138 000012AD F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3139 000012B0 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3140                              <1> 		; 20/02/2015 
  3141 000012B2 BB[18650000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3142 000012B7 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3143                              <1> 	;
  3144                              <1> 	;-----	TRANSLATE THE CHARACTER
  3145                              <1> K56:					; TRANSLATE-CHAR
  3146 000012B9 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3147 000012BB D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3148 000012BC F605[76650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3149 000012C3 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3150 000012C5 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3151 000012C7 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3152                              <1> 	;
  3153                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3154                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3155 000012C9 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3156 000012CB D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3157 000012CC 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3158 000012CE B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3159 000012D0 F605[76650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3160 000012D7 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3161 000012D9 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3162                              <1> 	;
  3163                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3164                              <1> K57:					; BUFFER_FILL
  3165 000012DB 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3166 000012DD 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3167                              <1> 	; 24/12/2021
  3168                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3169 000012DF 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3170                              <1> 	; 24/12/2021
  3171 000012E2 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3172                              <1> 	;je	K26			; INTERRUPT_RETURN
  3173                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3174 000012E4 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3175                              <1> K61:					; NOT-CAPS-STATE
  3176 000012E9 8B1D[84650000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3177 000012EF 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3178 000012F1 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3179 000012F6 3B1D[80650000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3180 000012FC 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3181 000012FE 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3182 00001301 891D[84650000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3183 00001307 E945FDFFFF          <1> 	jmp	K26
  3184                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3185                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3186                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3187                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3188                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3189                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3190                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3191                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3192                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3193                              <1> 	;;jmp   K27                    
  3194                              <1> 	;
  3195                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3196                              <1> K62:
  3197 0000130C B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3198 0000130E E620                <1> 	out	INTA00, al
  3199 00001310 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3200 00001314 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3201 00001316 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3202 0000131B E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3203                              <1> 
  3204                              <1> SHIP_IT:
  3205                              <1> 	;---------------------------------------------------------------------------------
  3206                              <1> 	; SHIP_IT
  3207                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3208                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3209                              <1> 	;---------------------------------------------------------------------------------
  3210                              <1> 	;
  3211                              <1> 	;push	ax			; SAVE DATA TO SEND
  3212                              <1> 	; 24/12/2021
  3213 00001320 50                  <1> 	push	eax
  3214                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3215 00001321 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3216                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3217 00001322 B900000100          <1> 	mov	ecx, 10000h			
  3218                              <1> S10:
  3219 00001327 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3220 00001329 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3221 0000132B E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3222                              <1> 
  3223                              <1> 	;pop	ax			; GET DATA TO SEND
  3224                              <1> 	; 24/12/2021
  3225 0000132D 58                  <1> 	pop	eax
  3226 0000132E E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3227 00001330 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3228 00001331 C3                  <1> 	retn				; RETURN TO CALLER
  3229                              <1> 
  3230                              <1> SND_DATA:
  3231                              <1> 	; ---------------------------------------------------------------------------------
  3232                              <1> 	; SND_DATA
  3233                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3234                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3235                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3236                              <1> 	; ---------------------------------------------------------------------------------
  3237                              <1> 	;
  3238                              <1> 	;push	ax			; SAVE REGISTERS
  3239                              <1> 	;push	bx
  3240                              <1> 	; 24/12/2021
  3241 00001332 50                  <1> 	push	eax
  3242 00001333 53                  <1> 	push	ebx
  3243 00001334 51                  <1> 	push	ecx
  3244 00001335 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3245 00001337 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3246                              <1> SD0:
  3247 00001339 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3248 0000133A 8025[75650000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3249                              <1> 	;
  3250                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3251 00001341 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3252                              <1> SD5:
  3253 00001346 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3254 00001348 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3255 0000134A E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3256                              <1> 	;
  3257 0000134C 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3258 0000134E E660                <1> 	out	PORT_A, al		; SEND BYTE
  3259 00001350 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3260                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3261 00001351 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3262                              <1> SD1:
  3263 00001356 F605[75650000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3264 0000135D 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3265 0000135F E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3266                              <1> SD2:
  3267 00001361 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3268 00001363 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3269 00001365 800D[75650000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3270 0000136C EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3271                              <1> SD3:
  3272 0000136E F605[75650000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3273 00001375 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3274                              <1> SD4:	
  3275 00001377 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3276                              <1> 	;pop	bx
  3277                              <1> 	;pop	ax
  3278                              <1> 	; 24/12/2021
  3279 00001378 5B                  <1> 	pop	ebx
  3280 00001379 58                  <1> 	pop	eax
  3281 0000137A C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3282                              <1> 
  3283                              <1> SND_LED:
  3284                              <1> 	; ---------------------------------------------------------------------------------
  3285                              <1> 	; SND_LED
  3286                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3287                              <1> 	;
  3288                              <1> 	;----------------------------------------------------------------------------------
  3289                              <1> 	;
  3290 0000137B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3291 0000137C F605[75650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3292 00001383 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3293                              <1> 	;
  3294 00001385 800D[75650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3295 0000138C B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3296 0000138E E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3297 00001390 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3298                              <1> SND_LED1:
  3299 00001392 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3300 00001393 F605[75650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3301 0000139A 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3302                              <1> 	;
  3303 0000139C 800D[75650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3304                              <1> SL0:
  3305 000013A3 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3306 000013A5 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3307 000013AA FA                  <1> 	cli
  3308 000013AB E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3309 000013B0 8025[75650000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3310 000013B7 0805[75650000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3311 000013BD F605[75650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3312 000013C4 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3313                              <1> 	;
  3314 000013C6 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3315 000013CB FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3316 000013CC F605[75650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3317 000013D3 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3318                              <1> SL2:
  3319 000013D5 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3320 000013D7 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3321 000013DC FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3322                              <1> SL3:
  3323 000013DD 8025[75650000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3324                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3325 000013E4 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3326 000013E5 C3                  <1> 	retn				; RETURN TO CALLER
  3327                              <1> 
  3328                              <1> MAKE_LED:
  3329                              <1> 	;---------------------------------------------------------------------------------
  3330                              <1> 	; MAKE_LED
  3331                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3332                              <1> 	;	THE MODE INDICATORS.
  3333                              <1> 	;---------------------------------------------------------------------------------
  3334                              <1> 	;
  3335                              <1> 	;push 	cx			; SAVE CX
  3336 000013E6 A0[73650000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3337 000013EB 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3338                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3339                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3340 000013ED C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3341 000013F0 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3342                              <1> 	;pop	cx
  3343 000013F2 C3                  <1> 	retn				; RETURN TO CALLER
  3344                              <1> 
  3345                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3346                              <1> 
  3347                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1771                                  
  1772                                  %include 'video.inc' ; 07/03/2015
  1773                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1774                              <1> ; Last Modification: 25/02/2022
  1775                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1776                              <1> ;
  1777                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1778                              <1> 
  1779                              <1> ; 02/02/2022 (simplified scroll up)
  1780                              <1> ; 16/01/2016
  1781                              <1> ; 30/06/2015
  1782                              <1> ; 27/06/2015
  1783                              <1> ; 11/03/2015
  1784                              <1> ; 02/09/2014
  1785                              <1> ; 30/08/2014
  1786                              <1> ; VIDEO FUNCTIONS
  1787                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1788                              <1> 
  1789                              <1> write_tty:
  1790                              <1> 	; 02/02/2022
  1791                              <1> 	; 13/08/2015
  1792                              <1> 	; 02/09/2014
  1793                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1794                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1795                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1796                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1797                              <1> 	;
  1798                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1799                              <1> 	;	   AL = Character to be written
  1800                              <1> 	;	   EBX = Video Page (0 to 7)
  1801                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1802                              <1> 
  1803                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1804                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1805                              <1> 
  1806                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1807                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1808                              <1> ;
  1809                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1810                              <1> ;
  1811                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1812                              <1> ;										:
  1813                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1814                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1815                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1816                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1817                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1818                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1819                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1820                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1821                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1822                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1823                              <1> ;   THE 0 COLOR IS USED.							:
  1824                              <1> ;   ENTRY --									:
  1825                              <1> ;     (AH) = CURRENT CRT MODE							:
  1826                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1827                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1828                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1829                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1830                              <1> ;   EXIT -- 									:
  1831                              <1> ;     ALL REGISTERS SAVED							:
  1832                              <1> ;--------------------------------------------------------------------------------
  1833                              <1> 
  1834 000013F3 FA                  <1> 	cli
  1835                              <1> 	;
  1836                              <1> 	; READ CURSOR (04/12/2013)
  1837                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1838 000013F4 08FF                <1> 	or	bh, bh
  1839                              <1> 	;jnz	beeper
  1840                              <1> 	; 02/02/2022
  1841 000013F6 7405                <1> 	jz	short u14
  1842 000013F8 E992000000          <1> 	jmp	beeper
  1843                              <1> u14:
  1844                              <1> 	; 02/02/2022
  1845                              <1> 	;; 01/09/2014
  1846                              <1> 	;cmp	byte [CRT_MODE], 3
  1847                              <1> 	;je	short m3
  1848                              <1> 	;;
  1849                              <1> 	;call	set_mode
  1850                              <1> m3:
  1851 000013FD 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1852                              <1> 	;shl	si, 1
  1853                              <1> 	; 02/02/2022
  1854 000013FF D1E6                <1> 	shl	esi, 1
  1855 00001401 81C6[666B0000]      <1> 	add	esi, cursor_posn
  1856 00001407 668B16              <1> 	mov	dx, [esi]
  1857                              <1> 	;
  1858                              <1> 	; dx now has the current cursor position
  1859                              <1> 	;
  1860 0000140A 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1861 0000140C 7647                <1> 	jbe	short u8
  1862                              <1> 	;
  1863                              <1> 	; write the char to the screen
  1864                              <1> u0:	
  1865                              <1> 	; ah = attribute/color
  1866                              <1> 	; al = character
  1867                              <1> 	; bl = video page number (0 to 7)
  1868                              <1> 	; bh = 0
  1869                              <1> 	;
  1870 0000140E E8D6010000          <1> 	call	write_c_current
  1871                              <1> 	;
  1872                              <1> 	; position the cursor for next char
  1873 00001413 FEC2                <1> 	inc	dl		; next column
  1874                              <1> 	;cmp	dl, [CRT_COLS]
  1875 00001415 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1876                              <1>         ;jne	set_cpos
  1877                              <1> 	; 02/02/2022
  1878 00001418 7405                <1> 	je	short u13
  1879 0000141A E9DE000000          <1> 	jmp	set_cpos
  1880                              <1> u13:
  1881 0000141F B200                <1> 	mov	dl, 0		; column = 0
  1882                              <1> u10:				; (line feed found)
  1883 00001421 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1884 00001424 7228                <1> 	jb 	short u6
  1885                              <1> 	;
  1886                              <1> 	; scroll required
  1887                              <1> u1:	
  1888                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1889 00001426 E8D2000000          <1> 	call	set_cpos
  1890                              <1> 	;
  1891                              <1> 	; determine value to fill with during scroll
  1892                              <1> u2:
  1893                              <1> 	; READ_AC_CURRENT		:
  1894                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1895                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1896                              <1> 	;
  1897                              <1> 	; INPUT				
  1898                              <1> 	;	(AH) = CURRENT CRT MODE
  1899                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1900                              <1> 	;	(DS) = DATA SEGMENT
  1901                              <1> 	;	(ES) = REGEN SEGMENT
  1902                              <1> 	; OUTPUT			
  1903                              <1> 	;	(AL) = CHARACTER READ
  1904                              <1> 	;	(AH) = ATTRIBUTE READ
  1905                              <1> 	;
  1906                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1907                              <1> 	;
  1908                              <1> 	; bl = video page number
  1909                              <1> 	;
  1910 0000142B E82D010000          <1> 	call	find_position	; get regen location and port address
  1911                              <1> 	; dx = status port
  1912                              <1> 	; esi = cursor location/address
  1913                              <1> p11:
  1914 00001430 FB                  <1> 	sti			; enable interrupts
  1915 00001431 90                  <1> 	nop			; allow for small interupts window
  1916 00001432 FA                  <1> 	cli			; blocks interrupts for single loop
  1917 00001433 EC                  <1> 	in	al, dx		; get status from adapter
  1918 00001434 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1919 00001436 75F8                <1> 	jnz	short p11	; wait until it is
  1920                              <1> p12:				; now wait for either retrace high
  1921 00001438 EC                  <1> 	in	al, dx		; get status
  1922 00001439 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1923 0000143B 74FB                <1> 	jz	short p12	; wait until either is active	
  1924                              <1> p13:
  1925 0000143D 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1926 00001443 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1927                              <1> 	;
  1928                              <1> 	; al = character, ah = attribute
  1929                              <1> 	;
  1930 00001446 FB                  <1> 	sti
  1931                              <1> 	; bl = video page number 	
  1932                              <1> u3:
  1933                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1934                              <1> 	;;sub	cx, cx		; upper left corner
  1935                              <1> 	;;mov	dh, 25-1 	; lower right row
  1936                              <1> 	;;;mov	dl, [CRT_COLS]
  1937                              <1> 	;mov	dl, 80		; lower right column	
  1938                              <1> 	;;dec	dl
  1939                              <1> 	;;mov	dl, 79
  1940                              <1> 
  1941                              <1> 	;;call	scroll_up	; 04/12/2013
  1942                              <1> 	;;; 11/03/2015
  1943                              <1> 	; 02/09/2014
  1944                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  1945                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  1946                              <1> 	; 11/03/2015
  1947                              <1> 	;sub	cx, cx
  1948                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  1949                              <1> 	;
  1950                              <1> 	; 02/02/2022 (simplied scroll up)
  1951                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  1952                              <1> 	;
  1953 00001447 B001                <1> 	mov	al, 1		; scroll 1 line up
  1954                              <1> 		; ah = attribute
  1955 00001449 E939010000          <1> 	jmp	scroll_up
  1956                              <1> ;u4:
  1957                              <1> 	;;int	10h		; video-call return
  1958                              <1> 				; scroll up the screen
  1959                              <1> 				; tty return
  1960                              <1> ;u5:
  1961                              <1> 	;retn			; return to the caller
  1962                              <1> 
  1963                              <1> u6:				; set-cursor-inc
  1964 0000144E FEC6                <1> 	inc	dh		; next row
  1965                              <1> 				; set cursor
  1966                              <1> ;u7:					
  1967                              <1> 	;;mov	ah, 02h
  1968                              <1> 	;;jmp	short u4 	; establish the new cursor
  1969                              <1> 	;call	set_cpos
  1970                              <1> 	;jmp 	short u5
  1971 00001450 E9A8000000          <1> 	jmp     set_cpos
  1972                              <1> 
  1973                              <1> 	; check for control characters
  1974                              <1> u8:
  1975 00001455 7434                <1> 	je	short u9
  1976 00001457 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  1977 00001459 74C6                <1> 	je	short u10
  1978 0000145B 3C07                <1> 	cmp	al, 07h 	; is it a bell
  1979 0000145D 7430                <1> 	je	short u11
  1980 0000145F 3C08                <1> 	cmp	al, 08h		; is it a backspace
  1981                              <1> 	;jne	short u0
  1982 00001461 7420                <1> 	je	short bs	; 12/12/2013
  1983                              <1> 	; 12/12/2013 (tab stop)
  1984 00001463 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  1985 00001465 75A7                <1> 	jne	short u0
  1986 00001467 88D0                <1> 	mov	al, dl
  1987 00001469 6698                <1> 	cbw
  1988 0000146B B108                <1> 	mov	cl, 8
  1989 0000146D F6F1                <1> 	div	cl
  1990 0000146F 28E1                <1> 	sub	cl, ah
  1991                              <1> ts:
  1992                              <1> 	; 02/09/2014
  1993                              <1> 	; 01/09/2014
  1994 00001471 B020                <1> 	mov	al, 20h
  1995                              <1> tsloop:
  1996                              <1> 	;push	cx
  1997                              <1> 	;push	ax
  1998                              <1> 	; 02/02/2022
  1999 00001473 51                  <1> 	push	ecx
  2000 00001474 50                  <1> 	push	eax
  2001 00001475 30FF                <1> 	xor 	bh, bh
  2002                              <1> 	;mov	bl, [active_page]
  2003 00001477 E881FFFFFF          <1> 	call	m3
  2004                              <1> 	; 02/02/2022
  2005 0000147C 58                  <1> 	pop	eax
  2006 0000147D 59                  <1>  	pop	ecx
  2007                              <1> 	;pop	ax  ; ah = attribute/color
  2008                              <1> 	;pop	cx
  2009 0000147E FEC9                <1> 	dec	cl
  2010 00001480 75F1                <1> 	jnz	short tsloop
  2011 00001482 C3                  <1> 	retn
  2012                              <1> bs:	
  2013                              <1> 	; back space found
  2014 00001483 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2015                              <1> 	;je	short u7 	; set_cursor
  2016 00001485 7476                <1> 	jz	short set_cpos
  2017                              <1> 	;dec	dx     		; no -- just move it back
  2018                              <1> 	; 02/02/2022
  2019 00001487 FECA                <1> 	dec	dl
  2020                              <1> 	;jmp	short u7
  2021 00001489 EB72                <1> 	jmp	short set_cpos
  2022                              <1> 
  2023                              <1> 	; carriage return found
  2024                              <1> u9:
  2025 0000148B B200                <1> 	mov	dl, 0 		; move to first column
  2026                              <1> 	;jmp	short u7
  2027 0000148D EB6E                <1> 	jmp	short set_cpos
  2028                              <1> 
  2029                              <1> 	; line feed found
  2030                              <1> ;u10:
  2031                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2032                              <1> ;	jne	short u6 	; no, just set the cursor
  2033                              <1> ;       jmp     u1              ; yes, scroll the screen
  2034                              <1> 
  2035                              <1> beeper: 
  2036                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2037                              <1> 	; 18/01/2014
  2038                              <1> 	; 03/12/2013
  2039                              <1> 	; bell found
  2040                              <1> u11:
  2041 0000148F FB                  <1> 	sti
  2042 00001490 3A1D[766B0000]      <1> 	cmp	bl, [active_page]
  2043 00001496 7551                <1> 	jne	short u12	; Do not sound the beep 
  2044                              <1> 				; if it is not written on the active page
  2045 00001498 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2046 0000149C B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2047                              <1> 	;call	beep		; sound the pod bell
  2048                              <1> 	;jmp	short u5 	; tty_return
  2049                              <1> 	;retn
  2050                              <1> 	
  2051                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2052                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2053                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2054                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2055                              <1> 
  2056                              <1> beep:
  2057                              <1> 	; 07/02/2015
  2058                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2059                              <1> 	; 18/01/2014
  2060                              <1> 	; 03/12/2013
  2061                              <1> 	;
  2062                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2063                              <1> 	;
  2064                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2065                              <1> 	;
  2066                              <1> 	; ENTRY:
  2067                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2068                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2069                              <1> 	; EXIT:			:
  2070                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2071                              <1> 
  2072 0000149E 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2073 0000149F FA                  <1> 	cli			; block interrupts during update
  2074 000014A0 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2075 000014A2 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2076 000014A4 EB00                <1> 	jmp	$+2		; I/O delay
  2077 000014A6 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2078 000014A8 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2079 000014AA EB00                <1> 	jmp	$+2		; I/O delay
  2080 000014AC 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2081 000014AE E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2082 000014B0 E461                <1> 	in	al, PORT_B	; get current setting of port
  2083 000014B2 88C4                <1> 	mov	ah, al		; save that setting
  2084 000014B4 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2085 000014B6 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2086                              <1> 	;popf	; 18/01/2014
  2087 000014B8 FB                  <1> 	sti
  2088                              <1> g7:				; 1/64 second per count (bl)
  2089 000014B9 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2090 000014BE E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2091 000014C3 FECB                <1> 	dec	bl		; (bl) length count expired?
  2092 000014C5 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2093                              <1> 	;
  2094                              <1> 	;pushf			; save interrupt status
  2095 000014C7 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2096 000014C8 E461                <1> 	in	al, PORT_B	; get current port value
  2097                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2098 000014CA 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2099 000014CC 20C4                <1>         and	ah, al		; someone turned them off during beep
  2100 000014CE 88E0                <1> 	mov	al, ah		; recover value of port
  2101                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2102 000014D0 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2103 000014D2 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2104                              <1> 	;popf			; restore interrupt flag state
  2105 000014D4 FB                  <1> 	sti
  2106 000014D5 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2107 000014DA E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2108                              <1> 	;pushf			; save interrupt status
  2109 000014DF FA                  <1> 	cli			; block interrupts during update
  2110 000014E0 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2111 000014E2 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2112 000014E4 08E0                <1> 	or	al, ah		; recover value of port_b
  2113 000014E6 E661                <1> 	out	PORT_B, al	; restore speaker status
  2114 000014E8 9D                  <1> 	popf			; restore interrupt flag state
  2115                              <1> u12:	
  2116 000014E9 C3                  <1> 	retn
  2117                              <1> 
  2118                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2119                              <1> 
  2120                              <1> WAITF:
  2121                              <1> waitf:
  2122                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2123                              <1> 	; 03/12/2013
  2124                              <1> 	;
  2125                              <1> ;	push	ax		; save work register (ah)	
  2126                              <1> ;waitf1:
  2127                              <1> 				; use timer 1 output bits
  2128                              <1> ;	in	al, PORT_B	; read current counter output status
  2129                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2130                              <1> ;	cmp	al, ah		; did it just change
  2131                              <1> ;	je	short waitf1	; wait for a change in output line
  2132                              <1> ;	;
  2133                              <1> ;	mov	ah, al		; save new lflag state
  2134                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2135                              <1> ;	;
  2136                              <1> ;	pop	ax		; restore (ah)
  2137                              <1> ;	retn			; return (cx)=0
  2138                              <1> 
  2139                              <1> ; 02/02/2022
  2140                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2141                              <1> ; 17/12/2014 (dsectrm2.s)
  2142                              <1> ; WAITF
  2143                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2144                              <1> ;
  2145                              <1> ;---WAITF-----------------------------------------------------------------------
  2146                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2147                              <1> ; ENTRY:
  2148                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2149                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2150                              <1> ; EXIT:
  2151                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2152                              <1> ;	(CX) = 0	
  2153                              <1> ;-------------------------------------------------------------------------------
  2154                              <1> 
  2155                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2156                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2157                              <1> 
  2158                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2159 000014EA 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2160                              <1> 	;push	ax
  2161                              <1> 	; 16/12/2014
  2162                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2163 000014EB D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2164                              <1> ;17/12/2014	
  2165                              <1> ;WAITF1:
  2166                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2167                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2168                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2169                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2170                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2171                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2172                              <1> 	;
  2173                              <1> 	; 17/12/2014
  2174                              <1> 	;
  2175                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2176                              <1> 	;
  2177                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2178                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2179                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2180                              <1> WR_STATE_0:
  2181 000014ED E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2182 000014EF A810                <1> 	TEST	AL,010H
  2183 000014F1 74FA                <1> 	JZ	SHORT WR_STATE_0
  2184                              <1> WR_STATE_1:
  2185 000014F3 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2186 000014F5 A810                <1> 	TEST	AL,010H
  2187 000014F7 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2188 000014F9 E2F2                <1>         LOOP    WR_STATE_0
  2189                              <1> 	;
  2190                              <1> 	;pop	ax
  2191 000014FB 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2192 000014FC C3                  <1> 	RETn				; (CX) = 0
  2193                              <1> 
  2194                              <1> set_cpos:
  2195                              <1> 	; 25/02/2022
  2196                              <1> 	; 23/02/2022
  2197                              <1> 	; 02/02/2022
  2198                              <1> 	; 27/06/2015
  2199                              <1> 	; 01/09/2014
  2200                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2201                              <1> 	;
  2202                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2203                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2204                              <1> 	;
  2205                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2206                              <1> 	;
  2207                              <1> 	; SET_CPOS
  2208                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2209                              <1> 	;	NEW X-Y VALUES PASSED
  2210                              <1> 	; INPUT
  2211                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2212                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2213                              <1> 	; OUTPUT
  2214                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2215                              <1> 	;
  2216 000014FD 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2217 00001500 D0E0                <1>         shl     al, 1   ; word offset
  2218 00001502 BE[666B0000]        <1> 	mov	esi, cursor_posn
  2219 00001507 01C6                <1>         add     esi, eax
  2220 00001509 668916              <1> 	mov	[esi], dx ; save the pointer
  2221 0000150C 381D[766B0000]      <1> 	cmp	[active_page], bl
  2222 00001512 7536                <1> 	jne	short m17
  2223                              <1> 	
  2224 00001514 FA                  <1> 	cli ; 25/02/2022
  2225                              <1> 
  2226                              <1> 	;call	m18	; CURSOR SET
  2227                              <1> ;m17:			; SET_CPOS_RETURN
  2228                              <1> 	; 01/09/2014
  2229                              <1> 	;retn
  2230                              <1> 		; DX = row/column
  2231                              <1> m18:
  2232 00001515 E835000000          <1> 	call	position ; determine location in regen buffer	
  2233                              <1> 	;mov	cx, [CRT_START]
  2234                              <1> 	; 23/02/2022
  2235 0000151A 0FB70D[646B0000]    <1> 	movzx	ecx, word [CRT_START]
  2236 00001521 01C1                <1> 	add	ecx, eax
  2237                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2238                              <1> 			; to the start address (offset) for this page
  2239                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2240                              <1> 	; 23/02/2022
  2241 00001523 D1E9                <1> 	shr	ecx, 1
  2242 00001525 B40E                <1> 	mov	ah, 14	; register number for cursor
  2243                              <1> 	
  2244 00001527 E802000000          <1> 	call	m16	; output value to the 6845
  2245 0000152C FB                  <1> 	sti	; 25/02/2022
  2246 0000152D C3                  <1> 	retn
  2247                              <1> 
  2248                              <1> 	; 25/02/2022
  2249                              <1> 	; 02/02/2022
  2250                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2251                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2252                              <1> m16:
  2253                              <1> 	;cli	; 25/02/2022
  2254                              <1> 	;mov	dx, [addr_6845] ; address register
  2255 0000152E 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2256 00001532 88E0                <1> 	mov	al, ah	; get value
  2257 00001534 EE                  <1> 	out	dx, al	; register set
  2258                              <1> 	;inc	dx	; data register
  2259                              <1> 	; 02/02/2022
  2260 00001535 FEC2                <1> 	inc	dl
  2261 00001537 EB00                <1> 	jmp	$+2	; i/o delay
  2262 00001539 88E8                <1> 	mov	al, ch	; data
  2263 0000153B EE                  <1> 	out	dx, al	
  2264                              <1> 	;dec	dx
  2265                              <1> 	; 02/02/2022	
  2266 0000153C FECA                <1> 	dec	dl
  2267 0000153E 88E0                <1> 	mov	al, ah
  2268 00001540 FEC0                <1> 	inc	al	; point to other data register
  2269 00001542 EE                  <1> 	out	dx, al	; set for second register
  2270                              <1> 	;inc	dx
  2271                              <1> 	; 02/02/2022
  2272 00001543 FEC2                <1> 	inc	dl
  2273 00001545 EB00                <1> 	jmp	$+2	; i/o delay
  2274 00001547 88C8                <1> 	mov	al, cl	; second data value
  2275 00001549 EE                  <1> 	out	dx, al
  2276                              <1> 	;sti	; 25/02/2022
  2277                              <1> m17:
  2278 0000154A C3                  <1> 	retn
  2279                              <1> 
  2280                              <1> set_ctype:
  2281                              <1> 	; 07/02/2022
  2282                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2283                              <1> 	;
  2284                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2285                              <1> 
  2286                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2287                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2288                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2289                              <1> ;          OR NO CURSOR AT ALL
  2290                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2291                              <1> 
  2292                              <1> ;------------------------------------------------
  2293                              <1> ; SET_CTYPE
  2294                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2295                              <1> ; INPUT
  2296                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2297                              <1> ; OUTPUT	
  2298                              <1> ;	NONE
  2299                              <1> ;------------------------------------------------
  2300                              <1> 
  2301 0000154B B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2302                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2303                              <1> 	;call	m16	; output cx register
  2304                              <1> 	;retn
  2305                              <1> 	; 07/02/2022
  2306 0000154D EBDF                <1> 	jmp	m16
  2307                              <1> 
  2308                              <1> position:
  2309                              <1> 	; 23/02/2022
  2310                              <1> 	; 02/02/2022
  2311                              <1> 	; 27/06/2015
  2312                              <1> 	; 02/09/2014
  2313                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2314                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2315                              <1> 	;
  2316                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2317                              <1> 	;
  2318                              <1> 	; POSITION
  2319                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2320                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2321                              <1> 	; INPUT
  2322                              <1> 	;	AX = ROW, COLUMN POSITION
  2323                              <1> 	; OUTPUT
  2324                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2325                              <1> 
  2326                              <1> 		; DX = ROW, COLUMN POSITION
  2327                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2328 0000154F 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2329 00001551 B050                <1> 	mov	al, 80	; determine bytes to row	
  2330 00001553 F6E6                <1> 	mul	dh	; row value
  2331                              <1> 	;xor	dh, dh	; 0
  2332                              <1> 	;add	ax, dx	; add column value to the result
  2333                              <1> 	; 23/02/2022
  2334 00001555 00D0                <1> 	add	al, dl
  2335 00001557 80D400              <1> 	adc	ah, 0	
  2336                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2337                              <1> 	; 02/02/2022
  2338 0000155A D1E0                <1> 	shl	eax, 1
  2339                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2340 0000155C C3                  <1> 	retn
  2341                              <1> 
  2342                              <1> find_position:
  2343                              <1> 	; 02/02/2022
  2344                              <1> 	; 27/06/2015
  2345                              <1> 	; 07/09/2014
  2346                              <1> 	; 02/09/2014
  2347                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2348                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2349 0000155D 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2350 00001560 89CE                <1> 	mov	esi, ecx
  2351                              <1> 	;shl	si, 1
  2352                              <1> 	; 02/02/2022
  2353 00001562 D1E6                <1> 	shl	esi, 1
  2354 00001564 668B96[666B0000]    <1> 	mov	dx, [esi+cursor_posn]
  2355 0000156B 7409                <1> 	jz	short p21
  2356                              <1> 	;xor	si, si
  2357                              <1> 	; 02/02/2022
  2358 0000156D 31F6                <1> 	xor	esi, esi
  2359                              <1> p20:
  2360                              <1> 	;add	si, [CRT_LEN]
  2361 0000156F 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2362 00001574 E2F9                <1> 	loop	p20
  2363                              <1> p21:
  2364 00001576 6621D2              <1> 	and	dx, dx
  2365 00001579 7407                <1> 	jz	short p22
  2366 0000157B E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2367 00001580 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2368                              <1> p22:	
  2369                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2370                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2371                              <1> 	;add	dx, 6	; point at status port
  2372 00001582 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2373                              <1> 	; cx = 0
  2374 00001586 C3                  <1> 	retn
  2375                              <1> 
  2376                              <1> scroll_up:
  2377                              <1> 	; 02/02/2022 (simplified scroll up)
  2378                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2379                              <1> 	; 16/01/2016
  2380                              <1> 	; 07/09/2014
  2381                              <1> 	; 02/09/2014
  2382                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2383                              <1> 	; 04/04/2014
  2384                              <1> 	; 04/12/2013
  2385                              <1> 	;
  2386                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2387                              <1> 	;
  2388                              <1> 	; SCROLL UP
  2389                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2390                              <1> 	;	ON THE SCREEN
  2391                              <1> 	; INPUT
  2392                              <1> 	;	(AH) = CURRENT CRT MODE
  2393                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2394                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2395                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2396                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2397                              <1> 	;	(DS) = DATA SEGMENT
  2398                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2399                              <1> 	; OUTPUT
  2400                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2401                              <1> 	;
  2402                              <1> 	;	bh = 0  (02/09/2014)
  2403                              <1> 	;
  2404                              <1> 	; ((ah = 3))
  2405                              <1> 	; cl = left upper column
  2406                              <1> 	; ch = left upper row
  2407                              <1> 	; dl = right lower column
  2408                              <1> 	; dh = right lower row
  2409                              <1> 	;
  2410                              <1> 	; al = line count 
  2411                              <1> 	; ah = attribute to be used on blanked line
  2412                              <1> 	; bl = video page number (0 to 7)
  2413                              <1> 	; 
  2414                              <1> 
  2415                              <1> 	; 02/02/2022 'scroll_up' code
  2416                              <1> 	; ------------------------------------------------------
  2417                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2418                              <1> 
  2419                              <1> 	; INPUT:
  2420                              <1> 	;		
  2421                              <1> 	; al = line count 
  2422                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2423                              <1> 	; ah = attribute to be used on blanked line
  2424                              <1> 	; bl = video page number (0 to 7)
  2425                              <1> 
  2426                              <1> 	;cli
  2427 00001587 31C9                <1> 	xor	ecx, ecx
  2428 00001589 88C1                <1> 	mov	cl, al ; line count (cl)
  2429 0000158B BE00800B00          <1> 	mov	esi, 0B8000h
  2430 00001590 3A1D[766B0000]      <1> 	cmp	bl, [active_page]
  2431 00001596 7411                <1> 	je	short n1
  2432 00001598 20DB                <1> 	and	bl, bl
  2433 0000159A 7422                <1> 	jz	short n3
  2434 0000159C 88DD                <1> 	mov	ch, bl ; video page number
  2435                              <1> n0:
  2436 0000159E 6681C6A00F          <1> 	add	si, 25*80*2
  2437 000015A3 FECD                <1> 	dec	ch
  2438 000015A5 75F7                <1> 	jnz	short n0
  2439 000015A7 EB15                <1> 	jmp	short n3
  2440                              <1> n1:
  2441 000015A9 660335[646B0000]    <1> 	add	si, [CRT_START]
  2442                              <1> 	;
  2443 000015B0 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2444                              <1> n2:			 ; wait_display_enable
  2445 000015B4 EC                  <1> 	in	al, dx	 ; get port
  2446 000015B5 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2447 000015B7 74FB                <1> 	jz	short n2 ; wait_display_enable
  2448 000015B9 B025                <1> 	mov	al, 25h
  2449 000015BB B2D8                <1> 	mov	dl, 0D8h ; address control port
  2450 000015BD EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2451                              <1> n3:
  2452                              <1> 	; cl = line count
  2453                              <1> 	; ah = attribute/color
  2454 000015BE 89F7                <1> 	mov	edi, esi
  2455 000015C0 20C9                <1> 	and	cl, cl
  2456 000015C2 741F                <1> 	jz	short n6
  2457 000015C4 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2458 000015C9 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2459 000015CD F366A5              <1> 	rep	movsw
  2460 000015D0 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2461                              <1> n4:
  2462                              <1> 	; ah = character attribute/cocor
  2463 000015D2 B020                <1> 	mov	al, 20h ; fill with blanks
  2464 000015D4 F366AB              <1> 	rep	stosw
  2465                              <1> 
  2466 000015D7 3A1D[766B0000]      <1> 	cmp	bl, [active_page]
  2467 000015DD 7503                <1> 	jne	short n5
  2468                              <1> 
  2469                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2470 000015DF B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2471                              <1> 	;mov	dx, 03D8h ; always set color card port
  2472 000015E1 EE                  <1> 	out	dx, al
  2473                              <1> n5:
  2474 000015E2 C3                  <1> 	retn
  2475                              <1> n6:
  2476                              <1> 	; clear video page
  2477 000015E3 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2478 000015E7 EBE9                <1> 	jmp	short n4
  2479                              <1> 
  2480                              <1> 	; 23/02/2022
  2481                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2482                              <1> 	; ------------------------------------------------------
  2483                              <1> 
  2484                              <1> 	; Test	Line Count
  2485                              <1> 	or	al, al
  2486                              <1> 	jz	short al_set
  2487                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2488                              <1> 	sub	bh, ch
  2489                              <1> 	inc	bh	; adjust difference by 1
  2490                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2491                              <1> 	jne	short al_set ; if not the we're all set
  2492                              <1> 	xor	al, al	; otherwise set al to zero
  2493                              <1> al_set:
  2494                              <1> 	xor	bh, bh	; 0
  2495                              <1> 	;push	ax
  2496                              <1> 	push	eax ; 23/02/2022
  2497                              <1> 	;mov 	esi, [crt_base]
  2498                              <1>         mov     esi, 0B8000h  
  2499                              <1>         cmp     bl, [active_page]
  2500                              <1> 	jne	short n0
  2501                              <1> 	;
  2502                              <1>         mov     ax, [CRT_START]
  2503                              <1>         add     si, ax
  2504                              <1>         jmp     short n1
  2505                              <1> n0:
  2506                              <1>         and     bl, bl
  2507                              <1> 	jz	short n1
  2508                              <1> 	mov	al, bl
  2509                              <1> n0x:
  2510                              <1>         ;add    si, [CRT_LEN]
  2511                              <1>         ;add    esi, 80*25*2 
  2512                              <1>         add     si, 80*25*2
  2513                              <1>         dec	al
  2514                              <1> 	jnz	short n0x
  2515                              <1> n1:	
  2516                              <1>         ; Scroll position
  2517                              <1> 	;push	dx ; 23/02/2022
  2518                              <1> 	mov	dx, cx	; now, upper left position in DX
  2519                              <1> 	call	position
  2520                              <1> 	add	esi, eax
  2521                              <1> 	mov	edi, esi
  2522                              <1> 	;pop	dx	; lower right position in DX
  2523                              <1> 	sub	dx, cx
  2524                              <1> 	inc	dh	; dh = #rows 
  2525                              <1> 	inc	dl	; dl = #cols in block
  2526                              <1> 	;pop	ax	; al = line count, ah = attribute
  2527                              <1> 	pop	eax ; 23/02/2022
  2528                              <1> 	xor	ecx, ecx
  2529                              <1> 	mov	cx, ax
  2530                              <1> 	;mov	ah, [CRT_COLS]
  2531                              <1> 	mov	ah, 80
  2532                              <1> 	mul	ah	; determine offset to from address
  2533                              <1> 	add	ax, ax  ; *2 for attribute byte
  2534                              <1> 	;
  2535                              <1> 	;push	ax	; offset 
  2536                              <1> 	;push	dx
  2537                              <1> 	; 23/02/2022
  2538                              <1> 	push	eax
  2539                              <1> 	push	edx
  2540                              <1> 	;
  2541                              <1> 	; 04/04/2014
  2542                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2543                              <1> n8:                      ; wait_display_enable
  2544                              <1>         in      al, dx   ; get port
  2545                              <1> 	test	al, RVRT ; wait for vertical retrace
  2546                              <1> 	jz	short n8 ; wait_display_enable
  2547                              <1> 	mov	al, 25h
  2548                              <1> 	mov	dl, 0D8h ; address control port
  2549                              <1> 	out	dx, al	; turn off video during vertical retrace
  2550                              <1> 	;pop	dx	; #rows, #cols
  2551                              <1>        	;pop	ax	; offset
  2552                              <1> 	; 23/02/2022
  2553                              <1> 	pop	edx
  2554                              <1> 	pop	eax
  2555                              <1> 	xchg	ax, cx	; 
  2556                              <1> 	; ecx = offset, al = line count, ah = attribute
  2557                              <1> ;n9:
  2558                              <1> 	or	al, al
  2559                              <1>         jz      short n3 
  2560                              <1>         add     esi, ecx ; from address for scroll
  2561                              <1> 	mov	bh, dh  ; #rows in block
  2562                              <1> 	sub	bh, al	; #rows to be moved
  2563                              <1> n2:
  2564                              <1> 	; Move rows
  2565                              <1> 	mov	cl, dl	; get # of cols to move
  2566                              <1> 	push	esi
  2567                              <1> 	push	edi	; save start address
  2568                              <1> n10:
  2569                              <1> 	movsw		; move that line on screen
  2570                              <1> 	dec	cl
  2571                              <1>         jnz     short n10
  2572                              <1> 	pop	edi
  2573                              <1> 	pop	esi	; recover addresses
  2574                              <1>         ;mov    cl, [CRT_COLS] 
  2575                              <1> 	;add	cl, cl
  2576                              <1>         ;mov    ecx, 80*2
  2577                              <1>         mov     cx, 80*2
  2578                              <1>         add     esi, ecx  ; next line
  2579                              <1>         add     edi, ecx
  2580                              <1> 	dec	bh	 ; count of lines to move
  2581                              <1> 	jnz	short n2 ; row loop
  2582                              <1> 	; bh = 0
  2583                              <1> 	mov	dh, al	 ; #rows	
  2584                              <1> n3:
  2585                              <1> 	; attribute in ah
  2586                              <1> 	mov	al, ' '	 ; fill with blanks
  2587                              <1> n3x:
  2588                              <1> 	; Clear rows
  2589                              <1>                 ; dh =  #rows
  2590                              <1>         mov	cl, dl	; get # of cols to clear
  2591                              <1>         push    edi     ; save address
  2592                              <1> n11:
  2593                              <1>         stosw           ; store fill character
  2594                              <1> 	dec	cl
  2595                              <1>         jnz     short n11
  2596                              <1>         pop     edi     ; recover address
  2597                              <1> 	;mov	cl, [CRT_COLS]
  2598                              <1> 	;add	cl, cl
  2599                              <1>         ;mov    ecx, 80*2
  2600                              <1>         mov	cl, 80*2
  2601                              <1>         add     edi, ecx
  2602                              <1> 	dec	dh
  2603                              <1> 	jnz	short n3x ; 16/01/2016
  2604                              <1> 	;
  2605                              <1> 	cmp	bl, [active_page]
  2606                              <1> 	jne	short n6
  2607                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2608                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2609                              <1> 	mov	dx, 03D8h ; always set color card port
  2610                              <1> 	out	dx, al
  2611                              <1> n6:
  2612                              <1> 	retn
  2613                              <1> 
  2614                              <1> %endif
  2615                              <1> 
  2616                              <1> write_c_current:
  2617                              <1> 	; 02/02/2022
  2618                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2619                              <1> 	; 18/01/2014
  2620                              <1> 	; 04/12/2013
  2621                              <1> 	;
  2622                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2623                              <1> 	;
  2624                              <1> 	; WRITE_C_CURRENT
  2625                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2626                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2627                              <1> 	; INPUT	
  2628                              <1> 	;	(AH) = CURRENT CRT MODE
  2629                              <1> 	;	(BH) = DISPLAY PAGE
  2630                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2631                              <1> 	;	(AL) = CHAR TO WRITE
  2632                              <1> 	;	(DS) = DATA SEGMENT
  2633                              <1> 	;	(ES) = REGEN SEGMENT
  2634                              <1> 	; OUTPUT
  2635                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2636                              <1> 
  2637 000015E9 FA                  <1> 	cli		
  2638                              <1> 	; bl = video page
  2639                              <1> 	; al = character
  2640                              <1> 	; ah = color/attribute
  2641                              <1> 	;push	dx
  2642                              <1> 	;push	ax	; save character & attribute/color
  2643                              <1> 	; 02/02/2022
  2644 000015EA 52                  <1> 	push	edx
  2645 000015EB 50                  <1> 	push	eax
  2646 000015EC E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2647                              <1> 	; esi = regen location
  2648                              <1> 	; dx = status port
  2649                              <1> 	;
  2650                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2651                              <1> 	;
  2652                              <1> p41:			; wait for horizontal retrace is low or vertical
  2653 000015F1 FB                  <1> 	sti		; enable interrupts first
  2654 000015F2 3A1D[766B0000]      <1>         cmp     bl, [active_page]
  2655 000015F8 7510                <1> 	jne	short p44 
  2656 000015FA FA                  <1> 	cli 		; block interrupts for single loop
  2657 000015FB EC                  <1> 	in	al, dx	; get status from the adapter
  2658 000015FC A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2659 000015FE 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2660 00001600 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2661 00001602 75ED                <1> 	jnz	short p41 ; wait until it is
  2662                              <1> p42:			; wait for either retrace high
  2663 00001604 EC                  <1> 	in	al, dx	; get status again
  2664 00001605 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2665 00001607 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2666                              <1> p43:	
  2667 00001609 FB                  <1> 	sti
  2668                              <1> p44:
  2669                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2670                              <1> 	; 02/02/2022
  2671 0000160A 58                  <1> 	pop	eax
  2672 0000160B 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2673                              <1> 			; Retro UNIX 386 v1 feature only!
  2674 00001611 668906              <1> 	mov	[esi], ax
  2675                              <1> 	;pop	dx
  2676                              <1> 	; 02/02/2022
  2677 00001614 5A                  <1> 	pop	edx
  2678 00001615 C3                  <1> 	retn
  2679                              <1> 
  2680                              <1> %if 0	; 02/02/2022
  2681                              <1> 
  2682                              <1> set_mode:
  2683                              <1> 	; 02/02/2022
  2684                              <1> 	; 16/01/2016
  2685                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2686                              <1> 	;
  2687                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2688                              <1> 
  2689                              <1> ;------------------------------------------------------
  2690                              <1> ; SET MODE					      :
  2691                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2692                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2693                              <1> ; INPUT						      :
  2694                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2695                              <1> ; OUTPUT					      :
  2696                              <1> ;	NONE					      :
  2697                              <1> ;------------------------------------------------------
  2698                              <1> 
  2699                              <1> 	push	edi ; 16/01/2016
  2700                              <1> 	push	ebx
  2701                              <1> 	push	edx
  2702                              <1> 	push	ecx ; 16/01/2016
  2703                              <1>         push    eax
  2704                              <1> 
  2705                              <1> 	;mov	dx, 03D4h 	; address or color card
  2706                              <1> 	mov	al, 3
  2707                              <1> ;M8:
  2708                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2709                              <1> 	mov	al, 29h
  2710                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2711                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2712                              <1> 	;push	dx  		; save port value
  2713                              <1> 	;add	dx, 4		; point to control register
  2714                              <1> 	mov	dx, 3D8h
  2715                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2716                              <1> 	;pop	dx
  2717                              <1> ;M9:
  2718                              <1> 	mov	ebx, video_params ; initialization table
  2719                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2720                              <1> 	;xchg 	ah, al
  2721                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2722                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2723                              <1> 	
  2724                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2725                              <1> 	; 02/02/2022
  2726                              <1> 	; dx = 3D8h
  2727                              <1> 	xor	ecx, ecx
  2728                              <1> 	mov	cl, 16
  2729                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2730                              <1> M10:			;  initialization loop
  2731                              <1> 	mov	al, ah 	; get 6845 register number
  2732                              <1> 	out	dx, al
  2733                              <1> 	;inc	dx      ; point to data port
  2734                              <1> 	; 02/02/2022
  2735                              <1> 	inc	dl ; 3D9h
  2736                              <1> 	inc	ah	; next register value
  2737                              <1> 	mov	al, [ebx] ; get table value
  2738                              <1> 	out	dx, al	; out to chip
  2739                              <1> 	inc	ebx	; next in table
  2740                              <1> 	;dec	dx	; back to pointer register
  2741                              <1> 	; 02/02/2022
  2742                              <1> 	dec	dl ; 3D8h
  2743                              <1> 	loop	M10	; do the whole table
  2744                              <1> 	
  2745                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2746                              <1> 	;xor	ax, ax  
  2747                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2748                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2749                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2750                              <1> 	; black background, light gray characeter color, space character
  2751                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2752                              <1> ;M13:			  ; clear buffer
  2753                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2754                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2755                              <1> 
  2756                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2757                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2758                              <1> 			 ; prepare to output to video enable port
  2759                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2760                              <1> 	; 02/02/2022
  2761                              <1> 	;mov	dx, 3D8h
  2762                              <1> 	; 
  2763                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2764                              <1> 	mov	al, 29h
  2765                              <1> 	out	dx, al	 ; set video enable port
  2766                              <1> 
  2767                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2768                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2769                              <1> 	;
  2770                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2771                              <1> 	;
  2772                              <1> ;-----	SET CURSOR POSITIONS
  2773                              <1> 	;push	edi
  2774                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2775                              <1> 	mov	edi, cursor_posn
  2776                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2777                              <1> 	xor	eax, eax
  2778                              <1> 	rep 	stosd	; fill with zeroes
  2779                              <1> 	;pop	edi
  2780                              <1> 
  2781                              <1> ;-----	SET UP OVERSCAN REGISTER
  2782                              <1> 	inc	dx	; set overscan port to a default
  2783                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2784                              <1> ;M14:
  2785                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2786                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2787                              <1> 
  2788                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2789                              <1> 	;
  2790                              <1> 	pop	eax
  2791                              <1> 	pop	ecx ; 16/01/2016
  2792                              <1> 	pop	edx
  2793                              <1> 	pop	ebx
  2794                              <1> 	pop	edi ; 16/01/2016
  2795                              <1> 	retn
  2796                              <1> 
  2797                              <1> %endif
  2798                              <1> 	
  2799                              <1> tty_sw:
  2800                              <1> 	; 02/02/2022
  2801                              <1> 	; 30/06/2015
  2802                              <1> 	; 27/06/2015 
  2803                              <1> 	; 07/09/2014
  2804                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2805                              <1> 	;
  2806                              <1> 	; (Modified registers : EAX)
  2807                              <1> 	;
  2808                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2809                              <1> 	;
  2810                              <1> ;act_disp_page:
  2811                              <1> 	; 30/06/2015
  2812                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2813                              <1> 	; 10/12/2013
  2814                              <1> 	; 04/12/2013
  2815                              <1> 	;
  2816                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2817                              <1> 	;
  2818                              <1> 	; ACT_DISP_PAGE
  2819                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2820                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2821                              <1> 	; INPUT
  2822                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2823                              <1> 	; OUTPUT
  2824                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2825                              <1> 
  2826                              <1> 	;cli
  2827                              <1> 
  2828 00001616 53                  <1> 	push	ebx
  2829                              <1> 	;push	cx
  2830                              <1> 	;push	dx
  2831                              <1> 	; 02/02/2022
  2832 00001617 51                  <1> 	push	ecx
  2833 00001618 52                  <1> 	push	edx
  2834                              <1> 	;
  2835 00001619 A2[766B0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2836                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2837                              <1> 	;mov	cx, 25*80*2
  2838                              <1> 	; 02/02/2022
  2839 0000161E B9A00F0000          <1> 	mov	ecx, 25*80*2
  2840                              <1> 	; 27/06/2015
  2841 00001623 0FB6D8              <1> 	movzx	ebx, al
  2842                              <1> 	; 02/02/2022
  2843 00001626 89D8                <1> 	mov	eax, ebx
  2844                              <1> 	;
  2845                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2846                              <1> 	;mul 	cx	; display page times regen length
  2847                              <1> 	; 02/02/2022
  2848 00001628 F7E1                <1> 	mul	ecx	
  2849                              <1> 	; 10/12/2013
  2850 0000162A 66A3[646B0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2851                              <1> 	;mov	cx, ax	; start address to cx
  2852                              <1> 	; 02/02/2022
  2853 00001630 89C1                <1> 	mov	ecx, eax
  2854                              <1> 	;sar	cx, 1
  2855                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2856                              <1> 	; 02/02/2022
  2857 00001632 D1E9                <1> 	shr	ecx, 1
  2858 00001634 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2859 00001636 E8F3FEFFFF          <1> 	call	m16
  2860                              <1> 	;sal	bx, 1
  2861                              <1> 	; 01/09/2014
  2862 0000163B D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2863 0000163D 81C3[666B0000]      <1> 	add	ebx, cursor_posn
  2864 00001643 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2865 00001646 E8CAFEFFFF          <1> 	call	m18
  2866                              <1> 	;
  2867                              <1> 	;pop	dx
  2868                              <1> 	;pop	cx
  2869                              <1> 	; 02/02/2022
  2870 0000164B 5A                  <1> 	pop	edx
  2871 0000164C 59                  <1> 	pop	ecx
  2872 0000164D 5B                  <1> 	pop	ebx
  2873                              <1> 	;
  2874                              <1> 	;sti
  2875                              <1> 	;
  2876 0000164E C3                  <1> 	retn
  2877                              <1> 
  2878                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2879                              <1> 
  2880                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1773                                  
  1774                                  setup_rtc_int:
  1775                                  ; source: http://wiki.osdev.org/RTC
  1776 0000164F FA                      	cli		; disable interrupts
  1777                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1778                                  	; in order to change this ...
  1779                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1780                                  	; (rate must be above 2 and not over 15)
  1781                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1782 00001650 B08A                    	mov	al, 8Ah 
  1783 00001652 E670                    	out	70h, al ; set index to register A, disable NMI
  1784 00001654 90                      	nop
  1785 00001655 E471                    	in	al, 71h ; get initial value of register A
  1786 00001657 88C4                    	mov 	ah, al
  1787 00001659 80E4F0                  	and	ah, 0F0h
  1788 0000165C B08A                    	mov	al, 8Ah 
  1789 0000165E E670                    	out	70h, al ; reset index to register A
  1790 00001660 88E0                    	mov	al, ah
  1791 00001662 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1792 00001664 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1793                                  	; enable RTC interrupt
  1794 00001666 B08B                    	mov	al, 8Bh ;
  1795 00001668 E670                    	out	70h, al ; select register B and disable NMI
  1796 0000166A 90                      	nop
  1797 0000166B E471                    	in	al, 71h ; read the current value of register B
  1798 0000166D 88C4                    	mov	ah, al  ;
  1799 0000166F B08B                    	mov 	al, 8Bh ;
  1800 00001671 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1801 00001673 88E0                    	mov	al, ah  ;
  1802 00001675 0C40                    	or	al, 40h ;
  1803 00001677 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1804 00001679 FB                      	sti
  1805 0000167A C3                      	retn
  1806                                  
  1807                                  ; Write memory information
  1808                                  ; Temporary Code
  1809                                  ; 06/11/2014
  1810                                  ; 14/08/2015 
  1811                                  memory_info:	
  1812 0000167B A1[4C6B0000]            	mov	eax, [memory_size] ; in pages
  1813 00001680 50                      	push	eax
  1814 00001681 C1E00C                  	shl	eax, 12		   ; in bytes
  1815 00001684 BB0A000000              	mov	ebx, 10
  1816 00001689 89D9                    	mov	ecx, ebx	   ; 10
  1817 0000168B BE[AF670000]            	mov	esi, mem_total_b_str	
  1818 00001690 E8B2000000              	call	bintdstr
  1819 00001695 58                      	pop	eax
  1820 00001696 B107                    	mov	cl, 7
  1821 00001698 BE[D3670000]            	mov	esi, mem_total_p_str
  1822 0000169D E8A5000000              	call	bintdstr	
  1823                                  	; 14/08/2015
  1824 000016A2 E8BD000000              	call	calc_free_mem
  1825                                  	; edx = calculated free pages
  1826                                  	; ecx = 0
  1827 000016A7 A1[506B0000]            	mov 	eax, [free_pages]
  1828 000016AC 39D0                    	cmp	eax, edx ; calculated free mem value 
  1829                                  		; and initial free mem value are same or not?
  1830 000016AE 751D                    	jne 	short pmim ; print mem info with '?' if not
  1831 000016B0 52                      	push 	edx ; free memory in pages	
  1832                                  	;mov 	eax, edx
  1833 000016B1 C1E00C                  	shl	eax, 12 ; convert page count
  1834                                  			; to byte count
  1835 000016B4 B10A                    	mov	cl, 10
  1836 000016B6 BE[F3670000]            	mov	esi, free_mem_b_str
  1837 000016BB E887000000              	call	bintdstr
  1838 000016C0 58                      	pop	eax
  1839 000016C1 B107                    	mov	cl, 7
  1840 000016C3 BE[17680000]            	mov	esi, free_mem_p_str
  1841 000016C8 E87A000000              	call	bintdstr
  1842                                  pmim:
  1843 000016CD BE[9D670000]            	mov	esi, msg_memory_info
  1844                                  pmim_nb:	
  1845 000016D2 AC                      	lodsb
  1846 000016D3 08C0                    	or	al, al
  1847 000016D5 740D                    	jz	short pmim_ok
  1848 000016D7 56                      	push	esi
  1849 000016D8 31DB                    	xor	ebx, ebx ; 0
  1850                                  			; Video page 0 (bl=0)
  1851 000016DA B407                    	mov	ah, 07h ; Black background, 
  1852                                  			; light gray forecolor
  1853 000016DC E812FDFFFF              	call	write_tty
  1854 000016E1 5E                      	pop	esi
  1855 000016E2 EBEE                    	jmp	short pmim_nb
  1856                                  pmim_ok:
  1857 000016E4 C3                      	retn
  1858                                  
  1859                                  ; Convert binary number to hexadecimal string
  1860                                  ; 10/05/2015  
  1861                                  ; dsectpm.s (28/02/2015)
  1862                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1863                                  ; 01/12/2014
  1864                                  ; 25/11/2014
  1865                                  ;
  1866                                  bytetohex:
  1867                                  	; INPUT ->
  1868                                  	; 	AL = byte (binary number)
  1869                                  	; OUTPUT ->
  1870                                  	;	AX = hexadecimal string
  1871                                  	;
  1872 000016E5 53                      	push	ebx
  1873 000016E6 31DB                    	xor	ebx, ebx
  1874 000016E8 88C3                    	mov	bl, al
  1875 000016EA C0EB04                  	shr	bl, 4
  1876 000016ED 8A9B[37170000]          	mov	bl, [ebx+hexchrs] 	 	
  1877 000016F3 86D8                    	xchg	bl, al
  1878 000016F5 80E30F                  	and	bl, 0Fh
  1879 000016F8 8AA3[37170000]          	mov	ah, [ebx+hexchrs] 
  1880 000016FE 5B                      	pop	ebx	
  1881 000016FF C3                      	retn
  1882                                  
  1883                                  wordtohex:
  1884                                  	; INPUT ->
  1885                                  	; 	AX = word (binary number)
  1886                                  	; OUTPUT ->
  1887                                  	;	EAX = hexadecimal string
  1888                                  	;
  1889 00001700 53                      	push	ebx
  1890 00001701 31DB                    	xor	ebx, ebx
  1891 00001703 86E0                    	xchg	ah, al
  1892 00001705 6650                    	push	ax
  1893 00001707 88E3                    	mov	bl, ah
  1894 00001709 C0EB04                  	shr	bl, 4
  1895 0000170C 8A83[37170000]          	mov	al, [ebx+hexchrs] 	 	
  1896 00001712 88E3                    	mov	bl, ah
  1897 00001714 80E30F                  	and	bl, 0Fh
  1898 00001717 8AA3[37170000]          	mov	ah, [ebx+hexchrs]
  1899 0000171D C1E010                  	shl	eax, 16
  1900 00001720 6658                    	pop	ax
  1901 00001722 5B                      	pop	ebx
  1902 00001723 EBC0                    	jmp	short bytetohex
  1903                                  	;mov	bl, al
  1904                                  	;shr	bl, 4
  1905                                  	;mov	bl, [ebx+hexchrs] 	 	
  1906                                  	;xchg	bl, al	 	
  1907                                  	;and	bl, 0Fh
  1908                                  	;mov	ah, [ebx+hexchrs] 
  1909                                  	;pop	ebx	
  1910                                  	;retn
  1911                                  
  1912                                  dwordtohex:
  1913                                  	; INPUT ->
  1914                                  	; 	EAX = dword (binary number)
  1915                                  	; OUTPUT ->
  1916                                  	;	EDX:EAX = hexadecimal string
  1917                                  	;
  1918 00001725 50                      	push	eax
  1919 00001726 C1E810                  	shr	eax, 16
  1920 00001729 E8D2FFFFFF              	call	wordtohex
  1921 0000172E 89C2                    	mov	edx, eax
  1922 00001730 58                      	pop	eax
  1923 00001731 E8CAFFFFFF              	call	wordtohex
  1924 00001736 C3                      	retn
  1925                                  
  1926                                  ; 10/05/2015
  1927                                  hex_digits:
  1928                                  hexchrs:
  1929 00001737 303132333435363738-     	db '0123456789ABCDEF'
  1929 00001740 39414243444546     
  1930                                  
  1931                                  ; Convert binary number to decimal/numeric string
  1932                                  ; 06/11/2014
  1933                                  ; Temporary Code
  1934                                  ;
  1935                                  
  1936                                  bintdstr:
  1937                                  	; EAX = binary number
  1938                                  	; ESI = decimal/numeric string address
  1939                                  	; EBX = divisor (10)
  1940                                  	; ECX = string length (<=10)
  1941 00001747 01CE                    	add	esi, ecx
  1942                                  btdstr0:
  1943 00001749 4E                      	dec	esi
  1944 0000174A 31D2                    	xor	edx, edx
  1945 0000174C F7F3                    	div	ebx
  1946 0000174E 80C230                  	add	dl, 30h
  1947 00001751 8816                    	mov	[esi], dl
  1948 00001753 FEC9                    	dec	cl
  1949 00001755 740C                    	jz	btdstr2
  1950 00001757 09C0                    	or	eax, eax
  1951 00001759 75EE                    	jnz	short btdstr0
  1952                                  btdstr1:
  1953 0000175B 4E                      	dec	esi
  1954 0000175C C60620                          mov     byte [esi], 20h ; blank space
  1955 0000175F FEC9                    	dec	cl
  1956 00001761 75F8                    	jnz	short btdstr1
  1957                                  btdstr2:
  1958 00001763 C3                      	retn
  1959                                  
  1960                                  ; Calculate free memory pages on M.A.T.
  1961                                  ; 06/11/2014
  1962                                  ; Temporary Code
  1963                                  ;
  1964                                  
  1965                                  calc_free_mem:
  1966 00001764 31D2                    	xor	edx, edx
  1967                                  	;xor	ecx, ecx
  1968 00001766 668B0D[606B0000]        	mov	cx, [mat_size] ; in pages
  1969 0000176D C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  1970 00001770 BE00001000              	mov	esi, MEM_ALLOC_TBL
  1971                                  cfm0:
  1972 00001775 AD                      	lodsd
  1973 00001776 51                      	push	ecx
  1974 00001777 B920000000              	mov	ecx, 32
  1975                                  cfm1:
  1976 0000177C D1E8                    	shr	eax, 1
  1977 0000177E 7301                    	jnc	short cfm2
  1978 00001780 42                      	inc	edx
  1979                                  cfm2:
  1980 00001781 E2F9                    	loop	cfm1
  1981 00001783 59                      	pop	ecx
  1982 00001784 E2EF                    	loop	cfm0
  1983 00001786 C3                      	retn
  1984                                  
  1985                                  %include 'diskio.inc'  ; 07/03/2015
  1986                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  1987                              <1> ; Last Modification: 24/12/2021
  1988                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  1989                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  1990                              <1> 
  1991                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  1992                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  1993                              <1> 
  1994                              <1> ; 06/02/2015
  1995                              <1> diskette_io:
  1996 00001787 9C                  <1> 	pushfd
  1997 00001788 0E                  <1> 	push 	cs
  1998 00001789 E809000000          <1> 	call 	DISKETTE_IO_1
  1999 0000178E C3                  <1> 	retn
  2000                              <1> 	
  2001                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2002                              <1> ;//////////////////////////////////////////////////////
  2003                              <1> 
  2004                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2005                              <1> 
  2006                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2007                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2008                              <1> ; 20/02/2015
  2009                              <1> ; 06/02/2015 (Retro UNIX 386 v1, unix386.s)
  2010                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2011                              <1> ;
  2012                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2013                              <1> ;
  2014                              <1> ; ADISK.EQU
  2015                              <1> 
  2016                              <1> ;----- Wait control constants 
  2017                              <1> 
  2018                              <1> ;amount of time to wait while RESET is active.
  2019                              <1> 
  2020                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2021                              <1> 					;at 250 KBS xfer rate.
  2022                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2023                              <1> 
  2024                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2025                              <1> 					;status register to become valid
  2026                              <1> 					;before re-reading.
  2027                              <1> 
  2028                              <1> ;After sending a byte to NEC, status register may remain
  2029                              <1> ;incorrectly set for 24 us.
  2030                              <1> 
  2031                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2032                              <1> 					;RQM low.
  2033                              <1> 
  2034                              <1> ; COMMON.MAC
  2035                              <1> ;
  2036                              <1> ;	Timing macros
  2037                              <1> ;
  2038                              <1> 
  2039                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2040                              <1> 		jmp short $+2
  2041                              <1> %endmacro		
  2042                              <1> 
  2043                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2044                              <1> 		jmp short $+2
  2045                              <1> 		jmp short $+2
  2046                              <1> %endmacro
  2047                              <1> 
  2048                              <1> %macro		NEWIODELAY 0
  2049                              <1> 		out	0EBh,al
  2050                              <1> %endmacro 
  2051                              <1> 
  2052                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2053                              <1> ;;; WAIT_FOR_MEM
  2054                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2055                              <1> ;WAIT_FDU_INT_HI	equ	1
  2056                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2057                              <1> ;;; WAIT_FOR_PORT
  2058                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2059                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2060                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2061                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2062                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2063                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2064                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2065                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2066                              <1> ;;; WAIT_REFRESH
  2067                              <1> ;amount of time to wait for head settle, per unit in parameter
  2068                              <1> ;table = 1 ms.
  2069                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2070                              <1> 
  2071                              <1> 
  2072                              <1> ; //////////////// DISKETTE I/O ////////////////
  2073                              <1> 
  2074                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2075                              <1> 
  2076                              <1> ;----------------------------------------
  2077                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2078                              <1> ;----------------------------------------
  2079                              <1> 
  2080                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2081                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2082                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2083                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2084                              <1> 
  2085                              <1> ;----------------------------------------
  2086                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2087                              <1> ;-------------------------------------------------------------------------------
  2088                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2089                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2090                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2091                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2092                              <1> 
  2093                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2094                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2095                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2096                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2097                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2098                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2099                              <1> 
  2100                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2101                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2102                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2103                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2104                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2105                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2106                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2107                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2108                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2109                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2110                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2111                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2112                              <1> 
  2113                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2114                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2115                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2116                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2117                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2118                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2119                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2120                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2121                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2122                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2123                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2124                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2125                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2126                              <1> 
  2127                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2128                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2129                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2130                              <1> 
  2131                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2132                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2133                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2134                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2135                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2136                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2137                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2138                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2139                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2140                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2141                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2142                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2143                              <1> 
  2144                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2145                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2146                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2147                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2148                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2149                              <1> 
  2150                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2151                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2152                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2153                              <1> INTA01		EQU	021H		; 8259 PORT
  2154                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2155                              <1> INTB01		EQU	0A1H		;
  2156                              <1> 
  2157                              <1> ;-------------------------------------------------------------------------------
  2158                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2159                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2160                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2161                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2162                              <1> ;-------------------------------------------------------------------------------
  2163                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2164                              <1> 
  2165                              <1> ;-------------------------------------------------------------------------------
  2166                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2167                              <1> 
  2168                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2169                              <1> ; (unix386.s <-- dsectrm2.s)
  2170                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2171                              <1> 
  2172                              <1> ; 10/12/2014
  2173                              <1> ;
  2174                              <1> ;int40h:
  2175                              <1> ;	pushf
  2176                              <1> ;	push 	cs
  2177                              <1> ;	;cli
  2178                              <1> ;	call 	DISKETTE_IO_1
  2179                              <1> ;	retn
  2180                              <1> 
  2181                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2182                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2183                              <1> ;
  2184                              <1> 
  2185                              <1> ;-- INT13H ---------------------------------------------------------------------
  2186                              <1> ; DISKETTE I/O
  2187                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2188                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2189                              <1> ; INPUT
  2190                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2191                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2192                              <1> ;		ON ALL DRIVES
  2193                              <1> ;------------------------------------------------------------------------------- 
  2194                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2195                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2196                              <1> ;-------------------------------------------------------------------------------
  2197                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2198                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2199                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2200                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2201                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2202                              <1> ;		320/360	320/360	    0-39
  2203                              <1> ;		320/360	1.2M	    0-39
  2204                              <1> ;		1.2M	1.2M	    0-79
  2205                              <1> ;		720K	720K	    0-79
  2206                              <1> ;		1.44M	1.44M	    0-79	
  2207                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2208                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2209                              <1> ;		320/360	320/360	     1-8/9
  2210                              <1> ;		320/360	1.2M	     1-8/9
  2211                              <1> ;		1.2M	1.2M	     1-15
  2212                              <1> ;		720K	720K	     1-9
  2213                              <1> ;		1.44M	1.44M	     1-18		
  2214                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2215                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2216                              <1> ;		320/360	320/360	        8/9
  2217                              <1> ;		320/360	1.2M	        8/9
  2218                              <1> ;		1.2M	1.2M		15
  2219                              <1> ;		720K	720K		9
  2220                              <1> ;		1.44M	1.44M		18
  2221                              <1> ;
  2222                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2223                              <1> ;
  2224                              <1> ;-------------------------------------------------------------------------------
  2225                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2226                              <1> ;-------------------------------------------------------------------------------
  2227                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2228                              <1> ;-------------------------------------------------------------------------------
  2229                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2230                              <1> ;-------------------------------------------------------------------------------
  2231                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2232                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2233                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2234                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2235                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2236                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2237                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2238                              <1> ;		READ/WRITE ACCESS.
  2239                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2240                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2241                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2242                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2243                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2244                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2245                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2246                              <1> ;
  2247                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2248                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2249                              <1> ;		---------------------------------------------
  2250                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2251                              <1> ;		---------------------------------------------
  2252                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2253                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2254                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2255                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2256                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2257                              <1> ;		---------------------------------------------
  2258                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2259                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2260                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2261                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2262                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2263                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2264                              <1> ;-------------------------------------------------------------------------------
  2265                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2266                              <1> ;	REGISTERS
  2267                              <1> ;	  INPUT
  2268                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2269                              <1> ;	  OUTPUT
  2270                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2271                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2272                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2273                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2274                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2275                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2276                              <1> ;	    (BH) - 0
  2277                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2278                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2279                              <1> ;	    (AX) - 0
  2280                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2281                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2282                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2283                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2284                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2285                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2286                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2287                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2288                              <1> ;-------------------------------------------------------------------------------
  2289                              <1> ;	(AH)= 15H  READ DASD TYPE
  2290                              <1> ;	OUTPUT REGISTERS
  2291                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2292                              <1> ;		00 - DRIVE NOT PRESENT	
  2293                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2294                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2295                              <1> ;		03 - RESERVED (FIXED DISK)
  2296                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2297                              <1> ;-------------------------------------------------------------------------------
  2298                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2299                              <1> ;	OUTPUT REGISTERS
  2300                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2301                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2302                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2303                              <1> ;-------------------------------------------------------------------------------
  2304                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2305                              <1> ;	INPUT REGISTERS
  2306                              <1> ;	(AL) -	00 - NOT USED	
  2307                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2308                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2309                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2310                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2311                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2312                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2313                              <1> ;-------------------------------------------------------------------------------
  2314                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2315                              <1> ;	INPUT REGISTERS
  2316                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2317                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2318                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2319                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2320                              <1> ;	OUTPUT REGISTERS:
  2321                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2322                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2323                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2324                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2325                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2326                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2327                              <1> ;-------------------------------------------------------------------------------
  2328                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2329                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2330                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2331                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2332                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2333                              <1> ;		CHANGE ERROR CODE
  2334                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2335                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2336                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2337                              <1> ;
  2338                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2339                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2340                              <1> ;-------------------------------------------------------------------------------
  2341                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2342                              <1> ;	AH = STATUS OF OPERATION
  2343                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2344                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2345                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2346                              <1> ;		TYPE AH=(15)).
  2347                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2348                              <1> ;	FOR READ/WRITE/VERIFY
  2349                              <1> ;		DS,BX,DX,CX PRESERVED
  2350                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2351                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2352                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2353                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2354                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2355                              <1> ;-------------------------------------------------------------------------------
  2356                              <1> ;
  2357                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2358                              <1> ;
  2359                              <1> ;   -----------------------------------------------------------------
  2360                              <1> ;   |       |       |       |       |       |       |       |       |
  2361                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2362                              <1> ;   |       |       |       |       |       |       |       |       |
  2363                              <1> ;   -----------------------------------------------------------------
  2364                              <1> ;	|	|	|	|	|	|	|	|
  2365                              <1> ;	|	|	|	|	|	-----------------
  2366                              <1> ;	|	|	|	|	|		|
  2367                              <1> ;	|	|	|	|    RESERVED		|
  2368                              <1> ;	|	|	|	|		  PRESENT STATE
  2369                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2370                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2371                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2372                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2373                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2374                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2375                              <1> ;	|	|	|	|	110: RESERVED
  2376                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2377                              <1> ;	|	|	|	|
  2378                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2379                              <1> ;	|	|	|
  2380                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2381                              <1> ;	|	|			DRIVE)
  2382                              <1> ;	|	|
  2383                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2384                              <1> ;
  2385                              <1> ;						00: 500 KBS
  2386                              <1> ;						01: 300 KBS
  2387                              <1> ;						10: 250 KBS
  2388                              <1> ;						11: RESERVED
  2389                              <1> ;
  2390                              <1> ;
  2391                              <1> ;-------------------------------------------------------------------------------
  2392                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2393                              <1> ;-------------------------------------------------------------------------------
  2394                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2395                              <1> ;-------------------------------------------------------------------------------
  2396                              <1> 
  2397                              <1> struc MD
  2398 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2399 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2400 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2401 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2402 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2403 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2404 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2405 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2406 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2407 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2408 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2409 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2410 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2411                              <1> endstruc
  2412                              <1> 
  2413                              <1> BIT7OFF	EQU	7FH
  2414                              <1> BIT7ON	EQU	80H
  2415                              <1> 
  2416                              <1> ;;int13h: ; 16/02/2015
  2417                              <1> ;; 16/02/2015 - 21/02/2015
  2418                              <1> int40h:
  2419 0000178F 9C                  <1> 	pushfd
  2420 00001790 0E                  <1> 	push 	cs
  2421 00001791 E801000000          <1> 	call 	DISKETTE_IO_1
  2422 00001796 C3                  <1> 	retn	
  2423                              <1> 
  2424                              <1> DISKETTE_IO_1:
  2425                              <1> 
  2426 00001797 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2427 00001798 55                  <1> 	PUSH	eBP			; USER REGISTER
  2428 00001799 57                  <1> 	PUSH	eDI			; USER REGISTER
  2429 0000179A 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2430 0000179B 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2431 0000179C 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2432 0000179D 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2433                              <1> 					; [BP]   = SECTOR #
  2434                              <1> 					; [BP+1] = TRACK #
  2435                              <1> 					; [BP+2] = BUFFER OFFSET
  2436                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2437                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2438                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2439                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2440                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2441                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2442                              <1> 					; BH/[BP+3] = 0
  2443                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2444                              <1> 					; DH/[BP+5] = MAX HEAD #
  2445                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2446 0000179F 06                  <1> 	push	es ; 06/02/2015	
  2447 000017A0 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2448 000017A1 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2449                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2450                              <1> 	;mov	cx, cs
  2451                              <1> 	;mov	ds, cx
  2452 000017A2 66B91000            <1> 	mov	cx, KDATA
  2453 000017A6 8ED9                <1>         mov     ds, cx
  2454 000017A8 8EC1                <1>         mov     es, cx
  2455                              <1> 
  2456                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2457 000017AA 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2458 000017AD 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2459 000017AF B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2460                              <1> OK_FUNC:
  2461 000017B1 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2462 000017B4 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2463 000017B6 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2464 000017B9 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2465 000017BB 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2466 000017BE 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2467 000017C0 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2468                              <1> OK_DRV:
  2469 000017C2 31C9                <1> 	xor	ecx, ecx
  2470                              <1> 	;mov	esi, ecx ; 08/02/2015
  2471                              <1> 	; 24/12/2021
  2472 000017C4 89CE                <1> 	mov	esi, ecx
  2473 000017C6 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2474 000017C8 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2475                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2476                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2477 000017CA C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2478 000017CD BB[05180000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2479 000017D2 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2480 000017D4 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2481 000017D6 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2482 000017D8 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2483 000017DB 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2484                              <1> 	;
  2485                              <1> 	; 11/12/2014
  2486 000017DE 8815[31660000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2487                              <1> 	;
  2488 000017E4 8A25[CC6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2489 000017EA C605[CC6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2490                              <1> 
  2491                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2492                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2493                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2494                              <1> ;
  2495                              <1> ;		DI	: DRIVE #
  2496                              <1> ;		SI-HI	: HEAD #
  2497                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2498                              <1> ;		ES	: BUFFER SEGMENT
  2499                              <1> ;		[BP]	: SECTOR #
  2500                              <1> ;		[BP+1]	: TRACK #
  2501                              <1> ;		[BP+2]	: BUFFER OFFSET
  2502                              <1> ;
  2503                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2504                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2505                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2506                              <1> ;	SPECIFIC ERROR CODE.
  2507                              <1> ;
  2508                              <1> 					; (AH) = @DSKETTE_STATUS
  2509 000017F1 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2510 000017F3 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2511 000017F4 1F                  <1> 	POP	DS
  2512 000017F5 07                  <1> 	pop	es	; 06/02/2015
  2513 000017F6 59                  <1> 	POP	eCX
  2514 000017F7 5B                  <1> 	POP	eBX
  2515 000017F8 5A                  <1> 	POP	eDX
  2516 000017F9 5F                  <1> 	POP	eDI
  2517 000017FA 89E5                <1> 	MOV	eBP, eSP
  2518 000017FC 50                  <1> 	PUSH	eAX
  2519 000017FD 9C                  <1> 	PUSHFd
  2520 000017FE 58                  <1> 	POP	eAX
  2521                              <1> 	;MOV	[BP+6], AX
  2522 000017FF 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2523 00001802 58                  <1> 	POP	eAX
  2524 00001803 5D                  <1> 	POP	eBP
  2525 00001804 CF                  <1> 	IRETd
  2526                              <1> 
  2527                              <1> ;-------------------------------------------------------------------------------
  2528                              <1> ; DW --> dd (06/02/2015)
  2529 00001805 [69180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2530 00001809 [DE180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2531 0000180D [EE180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2532 00001811 [FF180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2533 00001815 [10190000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2534 00001819 [21190000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2535 0000181D [A5190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2536 00001821 [A5190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2537 00001825 [B1190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2538 00001829 [A5190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2539 0000182D [A5190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2540 00001831 [A5190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2541 00001835 [A5190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2542 00001839 [A5190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2543 0000183D [A5190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2544 00001841 [A5190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2545 00001845 [A5190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2546 00001849 [A5190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2547 0000184D [A5190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2548 00001851 [A5190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2549 00001855 [A5190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2550 00001859 [701A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2551 0000185D [981A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2552 00001861 [D11A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2553 00001865 [521B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2554                              <1> FNC_TAE EQU     $                       ; END
  2555                              <1> 
  2556                              <1> ;-------------------------------------------------------------------------------
  2557                              <1> ; DISK_RESET	(AH = 00H)	
  2558                              <1> ;		RESET THE DISKETTE SYSTEM.
  2559                              <1> ;
  2560                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2561                              <1> ;-------------------------------------------------------------------------------
  2562                              <1> DSK_RESET:
  2563 00001869 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2564 0000186D FA                  <1> 	CLI				; NO INTERRUPTS
  2565 0000186E A0[CA6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2566 00001873 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2567 00001875 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2568                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2569 00001878 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2570 0000187A EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2571 0000187B C605[C96B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2572                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2573                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2574                              <1> 					;      PULSE WIDTH)
  2575                              <1> 	; 19/12/2014
  2576                              <1> 	NEWIODELAY
  2049 00001882 E6EB                <2>  out 0EBh,al
  2577                              <1> 
  2578                              <1> 	; 17/12/2014 
  2579                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2580 00001884 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2581                              <1> wdw1:
  2582                              <1> 	NEWIODELAY   ; 27/02/2015
  2049 00001889 E6EB                <2>  out 0EBh,al
  2583 0000188B E2FC                <1> 	loop	wdw1
  2584                              <1> 	;
  2585 0000188D 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2586 0000188F EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2587                              <1> 	; 16/12/2014
  2588                              <1> 	IODELAY
  2044 00001890 EB00                <2>  jmp short $+2
  2045 00001892 EB00                <2>  jmp short $+2
  2589                              <1> 	;
  2590                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2591 00001894 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2592 00001899 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2593 0000189B 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2594                              <1> NXT_DRV:
  2595                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2596                              <1> 	; 24/12/2021
  2597 0000189F 51                  <1> 	push	ecx
  2598 000018A0 B8[D4180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2599 000018A5 50                  <1> 	PUSH	eAX			; "
  2600 000018A6 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2601 000018A8 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2602 000018AD 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2603 000018AE E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2604                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2605                              <1> 	; 24/12/2021
  2606 000018B3 59                  <1> 	pop	ecx
  2607 000018B4 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2608 000018B6 3A0D[CD6B0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2609 000018BC 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2610 000018BE FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2611 000018C0 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2612 000018C3 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2613                              <1> 	;
  2614 000018C5 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2615                              <1> RESBAC:
  2616 000018CA E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2617                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2618                              <1> 	; 24/12/2021
  2619 000018CF 89F3                <1> 	mov	ebx, esi
  2620 000018D1 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2621 000018D3 C3                  <1> 	RETn		
  2622                              <1> DR_POP_ERR:
  2623                              <1> 	;POP	CX			; CLEAR STACK
  2624                              <1> 	; 24/12/2021
  2625 000018D4 59                  <1> 	pop	ecx
  2626                              <1> DR_ERR:
  2627 000018D5 800D[CC6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2628 000018DC EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2629                              <1> 
  2630                              <1> ;-------------------------------------------------------------------------------
  2631                              <1> ; DISK_STATUS	(AH = 01H)
  2632                              <1> ;	DISKETTE STATUS.
  2633                              <1> ;
  2634                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2635                              <1> ;
  2636                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2637                              <1> ;-------------------------------------------------------------------------------
  2638                              <1> DSK_STATUS:
  2639 000018DE 8825[CC6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2640 000018E4 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2641                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2642                              <1> 	; 24/12/2021
  2643 000018E9 89F3                <1> 	mov	ebx, esi
  2644 000018EB 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2645 000018ED C3                  <1> 	RETn		
  2646                              <1> 
  2647                              <1> ;-------------------------------------------------------------------------------
  2648                              <1> ; DISK_READ	(AH = 02H)	
  2649                              <1> ;	DISKETTE READ.
  2650                              <1> ;
  2651                              <1> ; ON ENTRY:	DI	: DRIVE #
  2652                              <1> ;		SI-HI	: HEAD #
  2653                              <1> ;		SI-LOW	: # OF SECTORS
  2654                              <1> ;		ES	: BUFFER SEGMENT
  2655                              <1> ;		[BP]	: SECTOR #
  2656                              <1> ;		[BP+1]	: TRACK #
  2657                              <1> ;		[BP+2]	: BUFFER OFFSET
  2658                              <1> ;
  2659                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2660                              <1> ;-------------------------------------------------------------------------------
  2661                              <1> 
  2662                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2663                              <1> 
  2664                              <1> DSK_READ:
  2665 000018EE 8025[CA6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2666 000018F5 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2667 000018F9 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2668 000018FE C3                  <1> 	RETn
  2669                              <1> 
  2670                              <1> ;-------------------------------------------------------------------------------
  2671                              <1> ; DISK_WRITE	(AH = 03H)
  2672                              <1> ;	DISKETTE WRITE.
  2673                              <1> ;
  2674                              <1> ; ON ENTRY:	DI	: DRIVE #
  2675                              <1> ;		SI-HI	: HEAD #
  2676                              <1> ;		SI-LOW	: # OF SECTORS
  2677                              <1> ;		ES	: BUFFER SEGMENT
  2678                              <1> ;		[BP]	: SECTOR #
  2679                              <1> ;		[BP+1]	: TRACK #
  2680                              <1> ;		[BP+2]	: BUFFER OFFSET
  2681                              <1> ;
  2682                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2683                              <1> ;-------------------------------------------------------------------------------
  2684                              <1> 
  2685                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2686                              <1> 
  2687                              <1> DSK_WRITE:
  2688 000018FF 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2689 00001903 800D[CA6B0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2690 0000190A E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2691 0000190F C3                  <1> 	RETn
  2692                              <1> 
  2693                              <1> ;-------------------------------------------------------------------------------
  2694                              <1> ; DISK_VERF	(AH = 04H)
  2695                              <1> ;	DISKETTE VERIFY.
  2696                              <1> ;
  2697                              <1> ; ON ENTRY:	DI	: DRIVE #
  2698                              <1> ;		SI-HI	: HEAD #
  2699                              <1> ;		SI-LOW	: # OF SECTORS
  2700                              <1> ;		ES	: BUFFER SEGMENT
  2701                              <1> ;		[BP]	: SECTOR #
  2702                              <1> ;		[BP+1]	: TRACK #
  2703                              <1> ;		[BP+2]	: BUFFER OFFSET
  2704                              <1> ;
  2705                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2706                              <1> ;-------------------------------------------------------------------------------
  2707                              <1> DSK_VERF:
  2708 00001910 8025[CA6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2709 00001917 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2710 0000191B E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2711 00001920 C3                  <1> 	RETn
  2712                              <1> 
  2713                              <1> ;-------------------------------------------------------------------------------
  2714                              <1> ; DISK_FORMAT	(AH = 05H)
  2715                              <1> ;	DISKETTE FORMAT.
  2716                              <1> ;
  2717                              <1> ; ON ENTRY:	DI	: DRIVE #
  2718                              <1> ;		SI-HI	: HEAD #
  2719                              <1> ;		SI-LOW	: # OF SECTORS
  2720                              <1> ;		ES	: BUFFER SEGMENT
  2721                              <1> ;		[BP]	: SECTOR #
  2722                              <1> ;		[BP+1]	: TRACK #
  2723                              <1> ;		[BP+2]	: BUFFER OFFSET
  2724                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2725                              <1> ;
  2726                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2727                              <1> ;-------------------------------------------------------------------------------
  2728                              <1> DSK_FORMAT:
  2729 00001921 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2730 00001926 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2731 0000192B 800D[CA6B0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2732 00001932 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2733 00001937 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2734 00001939 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2735 0000193E E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2736 00001943 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2737 00001945 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2738                              <1> FM_WR:
  2739 0000194A E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2740 0000194F 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2741 00001951 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2742 00001953 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2743 00001958 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2744 0000195A B8[96190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2745 0000195F 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2746 00001960 B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2747 00001962 E80E090000          <1> 	CALL	GET_PARM
  2748 00001967 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2749 0000196C B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2750 0000196E E802090000          <1> 	CALL	GET_PARM
  2751 00001973 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2752 00001978 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2753 0000197A E8F6080000          <1> 	CALL	GET_PARM
  2754 0000197F E8F7090000          <1> 	CALL	NEC_OUTPUT
  2755 00001984 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2756 00001986 E8EA080000          <1> 	CALL	GET_PARM
  2757 0000198B E8EB090000          <1> 	CALL	NEC_OUTPUT
  2758 00001990 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2759 00001991 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2760                              <1> FM_DON:
  2761 00001996 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2762 0000199B E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2763                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2764 000019A0 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2765 000019A2 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2766 000019A4 C3                  <1> 	RETn
  2767                              <1> 
  2768                              <1> ;-------------------------------------------------------------------------------
  2769                              <1> ; FNC_ERR
  2770                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2771                              <1> ;	SET BAD COMMAND IN STATUS.
  2772                              <1> ;
  2773                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2774                              <1> ;-------------------------------------------------------------------------------
  2775                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2776                              <1> 	;MOV	AX,SI			; RESTORE AL
  2777                              <1> 	; 24/12/2021
  2778 000019A5 89F0                <1> 	mov	eax, esi
  2779 000019A7 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2780 000019A9 8825[CC6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2781 000019AF F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2782 000019B0 C3                  <1> 	RETn
  2783                              <1> 
  2784                              <1> ;-------------------------------------------------------------------------------
  2785                              <1> ; DISK_PARMS	(AH = 08H)	
  2786                              <1> ;	READ DRIVE PARAMETERS.
  2787                              <1> ;
  2788                              <1> ; ON ENTRY:	DI : DRIVE #
  2789                              <1> ;
  2790                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2791                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2792                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2793                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2794                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2795                              <1> ;		BH/[BP+3] = 0
  2796                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2797                              <1> ;		DH/[BP+5] = MAX HEAD #
  2798                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2799                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2800                              <1> ;		AX        = 0
  2801                              <1> ;
  2802                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2803                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2804                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2805                              <1> ;		       CALLER.
  2806                              <1> ;-------------------------------------------------------------------------------
  2807                              <1> DSK_PARMS:
  2808 000019B1 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2809                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2810 000019B6 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2811 000019B8 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2812                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2813                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2814                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2815                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2816                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2817                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2818                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2819                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2820                              <1> 	;sub	edx, edx
  2821 000019BB 66A1[3E660000]      <1> 	mov     ax, [fd0_type]
  2822 000019C1 6621C0              <1> 	and     ax, ax
  2823 000019C4 7473                <1> 	jz      short NON_DRV
  2824 000019C6 FEC2                <1> 	inc     dl
  2825 000019C8 20E4                <1> 	and     ah, ah
  2826 000019CA 7402                <1> 	jz      short STO_DL
  2827 000019CC FEC2                <1> 	inc     dl
  2828                              <1> STO_DL:
  2829                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2830 000019CE 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2831 000019D1 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2832 000019D5 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2833                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2834 000019D7 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2835 000019DB E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2836                              <1> 	;;20/02/2015
  2837                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2838                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2839 000019E0 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2840 000019E2 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2841 000019E7 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2842                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2843 000019E9 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2844 000019EC 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2845 000019EF 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2846 000019F2 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2847                              <1> CHK_EST:
  2848 000019F4 8AA7[D96B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2849 000019FA F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2850 000019FD 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2851                              <1> USE_EST:
  2852 000019FF 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2853 00001A02 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2854 00001A05 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2855                              <1> 
  2856                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2857                              <1> 
  2858 00001A07 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2859 00001A09 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2860 00001A0E 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2861 00001A11 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2862 00001A14 F687[D96B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2863 00001A1B 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2864                              <1> 
  2865                              <1> ;-----	IT IS 1.44 MB DRIVE
  2866                              <1> 
  2867                              <1> PARM144:
  2868 00001A1D B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2869 00001A1F E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2870 00001A24 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2871 00001A27 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2872                              <1> STO_CX:
  2873 00001A2A 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2874                              <1> ES_DI:
  2875                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2876 00001A2D 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2877                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2878                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2879                              <1> DP_OUT:
  2880 00001A30 E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2881                              <1> 	;XOR	AX,AX			; CLEAR
  2882                              <1> 	; 24/12/2021
  2883 00001A35 31C0                <1> 	xor	eax, eax
  2884 00001A37 F8                  <1> 	CLC
  2885 00001A38 C3                  <1> 	RETn
  2886                              <1> 
  2887                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2888                              <1> 
  2889                              <1> NON_DRV:
  2890                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2891 00001A39 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2892                              <1> NON_DRV1:
  2893 00001A3C 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2894 00001A41 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2895                              <1> 
  2896                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2897                              <1> 	
  2898 00001A43 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2899                              <1> 	;MOV	AX,SI			; RESTORE AL
  2900 00001A48 89F0                <1> 	mov	eax, esi ; 24/12/2021
  2901 00001A4A B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2902 00001A4C F9                  <1> 	STC
  2903 00001A4D C3                  <1> 	RETn
  2904                              <1> 
  2905                              <1> NON_DRV2:
  2906                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2907 00001A4E 31C0                <1> 	xor	eax, eax	
  2908 00001A50 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2909                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2910 00001A54 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2911                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2912 00001A57 89450C              <1> 	mov	[ebp+12], eax
  2913                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2914 00001A5A EBD4                <1> 	JMP	SHORT DP_OUT
  2915                              <1> 
  2916                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  2917                              <1> 
  2918                              <1> USE_EST2:
  2919 00001A5C B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  2920 00001A5E E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2921 00001A63 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2922 00001A66 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2923 00001A69 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  2924 00001A6C 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  2925 00001A6E EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  2926                              <1> 
  2927                              <1> ;-------------------------------------------------------------------------------
  2928                              <1> ; DISK_TYPE (AH = 15H)	
  2929                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  2930                              <1> ;
  2931                              <1> ;  ON ENTRY:	DI = DRIVE #
  2932                              <1> ;
  2933                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  2934                              <1> ;-------------------------------------------------------------------------------
  2935                              <1> DSK_TYPE:
  2936 00001A70 E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2937 00001A75 8A87[D96B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  2938 00001A7B 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  2939 00001A7D 7415                <1> 	JZ	short NO_DRV
  2940 00001A7F B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  2941 00001A81 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  2942 00001A83 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  2943 00001A85 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  2944                              <1> DT_BACK:
  2945                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  2946 00001A87 50                  <1> 	push	eax ; 24/12/2021
  2947 00001A88 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2948                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  2949 00001A8D 58                  <1> 	pop	eax ; 24/12/2021
  2950 00001A8E F8                  <1> 	CLC				; NO ERROR
  2951                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2952                              <1> 	; 24/12/2021
  2953 00001A8F 89F3                <1> 	mov	ebx, esi
  2954 00001A91 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2955 00001A93 C3                  <1> 	RETn
  2956                              <1> NO_DRV:	
  2957 00001A94 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  2958 00001A96 EBEF                <1> 	JMP	SHORT DT_BACK
  2959                              <1> 
  2960                              <1> ;-------------------------------------------------------------------------------
  2961                              <1> ; DISK_CHANGE	(AH = 16H)
  2962                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  2963                              <1> ;
  2964                              <1> ; ON ENTRY:	DI = DRIVE #
  2965                              <1> ;
  2966                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  2967                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  2968                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  2969                              <1> ;-------------------------------------------------------------------------------
  2970                              <1> DSK_CHANGE:
  2971 00001A98 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2972 00001A9D 8A87[D96B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  2973 00001AA3 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  2974 00001AA5 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  2975 00001AA7 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  2976 00001AA9 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  2977                              <1> DC0:
  2978 00001AAB E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  2979 00001AB0 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  2980                              <1> 
  2981 00001AB2 C605[CC6B0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  2982                              <1> 
  2983 00001AB9 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2984 00001ABE E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2985                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2986                              <1> 	; 24/12/2021
  2987 00001AC3 89F3                <1> 	mov	ebx, esi
  2988 00001AC5 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2989 00001AC7 C3                  <1> 	RETn
  2990                              <1> DC_NON:
  2991 00001AC8 800D[CC6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  2992 00001ACF EBE8                <1> 	JMP	SHORT FINIS
  2993                              <1> 
  2994                              <1> ;-------------------------------------------------------------------------------
  2995                              <1> ; FORMAT_SET	(AH = 17H)
  2996                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  2997                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  2998                              <1> ;
  2999                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3000                              <1> ;		DI     = DRIVE #
  3001                              <1> ;
  3002                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3003                              <1> ;		AH = @DSKETTE_STATUS
  3004                              <1> ;		CY = 1 IF ERROR
  3005                              <1> ;-------------------------------------------------------------------------------
  3006                              <1> FORMAT_SET:
  3007 00001AD1 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3008                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3009                              <1> 	; 24/12/2021
  3010 00001AD6 56                  <1> 	push	esi
  3011 00001AD7 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3012 00001ADA 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3013 00001ADC 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3014 00001ADF 80A7[D96B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3015 00001AE6 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3016 00001AE8 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3017 00001AEA 808F[D96B0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3018 00001AF1 EB48                <1> 	JMP	SHORT S0
  3019                              <1> NOT_320:
  3020 00001AF3 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3021 00001AF8 803D[CC6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3022 00001AFF 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3023                              <1> S3:
  3024 00001B01 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3025 00001B03 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3026 00001B05 808F[D96B0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3027 00001B0C EB2D                <1> 	JMP	SHORT S0
  3028                              <1> NOT_320_12:
  3029 00001B0E 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3030 00001B10 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3031 00001B12 808F[D96B0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3032 00001B19 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3033                              <1> NOT_12:	
  3034 00001B1B 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3035 00001B1D 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3036                              <1> 
  3037 00001B1F F687[D96B0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3038 00001B26 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3039 00001B28 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3040 00001B2A F687[D96B0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3041 00001B31 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3042                              <1> ASSUME:
  3043 00001B33 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3044                              <1> OR_IT_IN:
  3045 00001B35 0887[D96B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3046                              <1> S0:
  3047 00001B3B E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3048 00001B40 E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3049                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3050                              <1> 	; 24/12/2021
  3051 00001B45 5B                  <1> 	pop	ebx
  3052 00001B46 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3053 00001B48 C3                  <1> 	RETn
  3054                              <1> FS_ERR:
  3055 00001B49 C605[CC6B0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3056 00001B50 EBE9                <1> 	JMP	SHORT S0
  3057                              <1> 
  3058                              <1> ;-------------------------------------------------------------------------------
  3059                              <1> ; SET_MEDIA	(AH = 18H)
  3060                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3061                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3062                              <1> ;
  3063                              <1> ; ON ENTRY:
  3064                              <1> ;	[BP]	= SECTOR PER TRACK
  3065                              <1> ;	[BP+1]	= TRACK #
  3066                              <1> ;	DI	= DRIVE #
  3067                              <1> ;
  3068                              <1> ; ON EXIT:
  3069                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3070                              <1> ;	IF NO ERROR:
  3071                              <1> ;		AH = 0
  3072                              <1> ;		CY = 0
  3073                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3074                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3075                              <1> ;	IF ERROR:	
  3076                              <1> ;		AH = @DSKETTE_STATUS
  3077                              <1> ;		CY = 1
  3078                              <1> ;-------------------------------------------------------------------------------
  3079                              <1> SET_MEDIA:
  3080 00001B52 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3081 00001B57 F687[D96B0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3082 00001B5E 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3083 00001B60 E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3084 00001B65 803D[CC6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3085 00001B6C 746B                <1> 	JE	short SM_RTN
  3086 00001B6E C605[CC6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3087                              <1> SM_CMOS:
  3088 00001B75 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3089                              <1> 	;;20/02/2015
  3090                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3091                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3092 00001B7A 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3093 00001B7C E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3094 00001B81 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3095 00001B83 57                  <1> 	PUSH	eDI			; SAVE REG.
  3096 00001B84 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3097 00001B86 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3098                              <1> DR_SEARCH:
  3099 00001B8B 8AA3[BC650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3100 00001B91 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3101 00001B94 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3102 00001B96 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3103                              <1> DR_FND:
  3104 00001B98 8BBB[BD650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3105                              <1> MD_SEARCH:
  3106 00001B9E 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3107 00001BA1 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3108 00001BA4 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3109 00001BA6 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3110 00001BA9 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3111 00001BAC 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3112                              <1> NXT_MD:
  3113                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3114 00001BAE 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3115 00001BB1 E2D8                <1> 	LOOP    DR_SEARCH
  3116 00001BB3 5F                  <1> 	POP	eDI			; RESTORE REG.
  3117                              <1> MD_NOT_FND:
  3118 00001BB4 C605[CC6B0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3119 00001BBB EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3120                              <1> MD_FND:
  3121 00001BBD 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3122 00001BC0 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3123 00001BC2 7502                <1> 	JNE	short MD_SET
  3124 00001BC4 0C20                <1> 	OR	AL,DBL_STEP
  3125                              <1> MD_SET:
  3126                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3127 00001BC6 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3128 00001BC9 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3129 00001BCB 5F                  <1> 	POP	eDI
  3130 00001BCC 80A7[D96B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3131 00001BD3 0887[D96B0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3132                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3133                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3134                              <1> SM_RTN:
  3135 00001BD9 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3136 00001BDE E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3137 00001BE3 C3                  <1> 	RETn
  3138                              <1> 
  3139                              <1> ;----------------------------------------------------------------
  3140                              <1> ; DR_TYPE_CHECK							:
  3141                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3142                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3143                              <1> ; ON ENTRY:							:
  3144                              <1> ;	AL = DRIVE TYPE						:
  3145                              <1> ; ON EXIT:							:
  3146                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3147                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3148                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3149                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3150                              <1> ; REGISTERS ALTERED: eBX						:
  3151                              <1> ;----------------------------------------------------------------		
  3152                              <1> DR_TYPE_CHECK:
  3153                              <1> 	;PUSH	AX			
  3154                              <1> 	; 24/12/2021
  3155 00001BE4 50                  <1> 	push	eax
  3156 00001BE5 51                  <1> 	PUSH	eCX
  3157 00001BE6 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3158 00001BE8 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3159                              <1> TYPE_CHK:	
  3160 00001BED 8AA3[BC650000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3161 00001BF3 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3162 00001BF5 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3163                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3164 00001BF7 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3165 00001BFA E2F1                <1> 	LOOP    TYPE_CHK
  3166                              <1> 	;
  3167 00001BFC BB[1B660000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3168                              <1> 					; Default for GET_PARM (11/12/2014)
  3169                              <1> 	;
  3170 00001C01 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3171 00001C02 EB06                <1> 	JMP	SHORT TYPE_RTN
  3172                              <1> DR_TYPE_VALID:
  3173 00001C04 8B9B[BD650000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3174                              <1> TYPE_RTN:
  3175 00001C0A 59                  <1> 	POP	eCX
  3176                              <1> 	;POP	AX
  3177                              <1> 	; 24/12/2021
  3178 00001C0B 58                  <1> 	pop	eax
  3179 00001C0C C3                  <1> 	RETn	
  3180                              <1> 		
  3181                              <1> ;----------------------------------------------------------------
  3182                              <1> ; SEND_SPEC							:
  3183                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3184                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3185                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3186                              <1> ; ON EXIT:	NONE						:	
  3187                              <1> ; REGISTERS ALTERED: CX, DX					:
  3188                              <1> ;----------------------------------------------------------------		
  3189                              <1> SEND_SPEC:
  3190 00001C0D 50                  <1> 	PUSH	eAX			; SAVE AX
  3191 00001C0E B8[341C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3192 00001C13 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3193 00001C14 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3194 00001C16 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3195 00001C1B 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3196 00001C1D E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3197 00001C22 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3198 00001C27 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3199 00001C29 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3200 00001C2E E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3201 00001C33 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3202                              <1> SPECBAC:
  3203 00001C34 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3204 00001C35 C3                  <1> 	RETn
  3205                              <1> 
  3206                              <1> ;----------------------------------------------------------------
  3207                              <1> ; SEND_SPEC_MD							:
  3208                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3209                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3210                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3211                              <1> ; ON EXIT:	NONE						:	
  3212                              <1> ; REGISTERS ALTERED: AX						:
  3213                              <1> ;----------------------------------------------------------------		
  3214                              <1> SEND_SPEC_MD:
  3215 00001C36 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3216 00001C37 B8[541C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3217 00001C3C 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3218 00001C3D B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3219 00001C3F E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3220 00001C44 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3221 00001C46 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3222 00001C4B 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3223 00001C4E E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3224 00001C53 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3225                              <1> SPEC_ESBAC:
  3226 00001C54 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3227 00001C55 C3                  <1> 	RETn
  3228                              <1> 
  3229                              <1> ;-------------------------------------------------------------------------------
  3230                              <1> ; XLAT_NEW  
  3231                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3232                              <1> ;	MODE TO NEW ARCHITECTURE.
  3233                              <1> ;
  3234                              <1> ; ON ENTRY:	DI = DRIVE #
  3235                              <1> ;-------------------------------------------------------------------------------
  3236                              <1> XLAT_NEW:
  3237 00001C56 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3238 00001C59 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3239 00001C5B 80BF[D96B0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3240 00001C62 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3241 00001C64 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3242 00001C67 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3243 00001C6A A0[D86B0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3244 00001C6F D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3245 00001C71 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3246 00001C73 80A7[D96B0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3247 00001C7A 0887[D96B0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3248                              <1> XN_OUT:
  3249 00001C80 C3                  <1> 	RETn
  3250                              <1> DO_DET:
  3251 00001C81 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3252 00001C86 C3                  <1> 	RETn
  3253                              <1> 
  3254                              <1> ;-------------------------------------------------------------------------------
  3255                              <1> ; XLAT_OLD 
  3256                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3257                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3258                              <1> ;
  3259                              <1> ; ON ENTRY:	DI = DRIVE
  3260                              <1> ;-------------------------------------------------------------------------------
  3261                              <1> XLAT_OLD:
  3262 00001C87 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3263                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3264                              <1>         ;ja	XO_OUT
  3265                              <1>         ; 24/12/2021
  3266 00001C8A 77F4                <1> 	ja	short XN_OUT
  3267 00001C8C 80BF[D96B0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3268 00001C93 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3269                              <1> 
  3270                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3271                              <1> 
  3272 00001C95 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3273 00001C98 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3274 00001C9B B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3275 00001C9D D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3276 00001C9F 8425[D86B0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3277 00001CA5 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3278                              <1> 
  3279                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3280                              <1> 
  3281 00001CA7 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3282 00001CA9 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3283 00001CAB F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3284 00001CAD 2025[D86B0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3285                              <1> 
  3286                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3287                              <1> 
  3288 00001CB3 8A87[D96B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3289 00001CB9 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3290 00001CBB D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3291 00001CBD 0805[D86B0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3292                              <1> 
  3293                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3294                              <1> 
  3295                              <1> SAVE_SET:
  3296 00001CC3 8AA7[D96B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3297 00001CC9 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3298 00001CCB 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3299 00001CCE 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3300 00001CD1 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3301 00001CD3 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3302 00001CD5 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3303 00001CD8 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3304 00001CDA F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3305 00001CDD 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3306                              <1> UNKNO:
  3307 00001CDF B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3308 00001CE1 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3309                              <1> CHK_144:
  3310 00001CE3 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3311                              <1> 	;;20/02/2015
  3312                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3313 00001CE8 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3314 00001CEA 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3315 00001CEC 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3316 00001CEE B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3317 00001CF0 EB0C                <1> 	JMP	SHORT TST_DET
  3318                              <1> CHK_250:
  3319 00001CF2 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3320 00001CF4 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3321 00001CF7 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3322 00001CF9 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3323 00001CFC 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3324                              <1> TST_DET:
  3325 00001CFE F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3326 00001D01 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3327 00001D03 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3328                              <1> AL_SET:
  3329 00001D05 80A7[D96B0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3330 00001D0C 0887[D96B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3331                              <1> XO_OUT:
  3332 00001D12 C3                  <1> 	RETn
  3333                              <1> 
  3334                              <1> ;-------------------------------------------------------------------------------
  3335                              <1> ; RD_WR_VF
  3336                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3337                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3338                              <1> ;
  3339                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3340                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3341                              <1> ;
  3342                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3343                              <1> ;-------------------------------------------------------------------------------
  3344                              <1> RD_WR_VF:
  3345                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3346 00001D13 50                  <1> 	push	eax ; 24/12/2021
  3347 00001D14 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3348 00001D19 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3349                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3350 00001D1E 58                  <1> 	pop	eax ; 24/12/2021
  3351                              <1> DO_AGAIN:
  3352                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3353 00001D1F 50                  <1> 	push	eax ; 24/12/2021
  3354 00001D20 E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3355                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3356 00001D25 58                  <1> 	pop	eax ; 24/12/2021
  3357                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3358                              <1> 	; 24/12/2021
  3359 00001D26 7305                <1> 	jnc	short RWV
  3360 00001D28 E9C3000000          <1> 	jmp	RWV_END
  3361                              <1> RWV:
  3362                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3363 00001D2D 50                  <1> 	push	eax ; 24/12/2021
  3364 00001D2E 8AB7[D96B0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3365 00001D34 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3366 00001D37 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3367                              <1> 	;;20/02/2015
  3368                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3369 00001D3C 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3370 00001D3E 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3371 00001D40 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3372 00001D42 F687[D96B0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3373 00001D49 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3374 00001D4B B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3375 00001D4D EB0F                <1> 	JMP	SHORT RWV_2
  3376                              <1> RWV_1:
  3377 00001D4F 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3378 00001D51 F687[D96B0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3379 00001D58 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3380 00001D5A B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3381 00001D5C EB04                <1> 	jmp	short rwv_3
  3382                              <1> RWV_2:
  3383 00001D5E 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3384 00001D60 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3385                              <1> rwv_3:
  3386 00001D62 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3387 00001D67 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3388                              <1> 
  3389                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3390                              <1> 
  3391 00001D69 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3392 00001D6A 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3393 00001D6C B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3394                              <1> RWV_DR_SEARCH:
  3395 00001D71 8AA3[BC650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3396 00001D77 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3397 00001D7A 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3398 00001D7C 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3399                              <1> RWV_DR_FND:
  3400 00001D7E 8BBB[BD650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3401                              <1> RWV_MD_SEARH:
  3402 00001D84 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3403 00001D87 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3404                              <1> RWV_NXT_MD:
  3405                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3406 00001D89 83C305              <1> 	add	eBX, 5
  3407 00001D8C E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3408 00001D8E 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3409                              <1> 
  3410                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3411                              <1> 
  3412                              <1> RWV_ASSUME:
  3413 00001D8F BB[DA650000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3414 00001D94 F687[D96B0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3415 00001D9B 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3416 00001D9D BB[F4650000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3417 00001DA2 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3418                              <1> 
  3419                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3420                              <1> 	 			
  3421                              <1> RWV_MD_FND:
  3422 00001DA4 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3423 00001DA6 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3424                              <1> 	
  3425                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3426                              <1> 
  3427                              <1> RWV_MD_FND1:
  3428 00001DA7 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3429 00001DAC E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3430 00001DB1 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3431 00001DB3 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3432                              <1> RWV_DBL:
  3433 00001DB8 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3434 00001DB9 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3435 00001DBE 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3436 00001DBF 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3437                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3438 00001DC1 58                  <1> 	pop	eax ; 24/12/2021
  3439                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3440 00001DC2 50                  <1> 	push	eax ; 24/12/2021
  3441 00001DC3 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3442 00001DC4 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3443 00001DC9 5B                  <1> 	POP	eBX 
  3444                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3445 00001DCA 58                  <1> 	pop	eax ; 24/12/2021
  3446 00001DCB 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3447                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3448 00001DCD 50                  <1> 	push	eax ; 24/12/2021
  3449 00001DCE 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3450 00001DCF E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3451 00001DD4 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3452 00001DD5 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3453 00001DD7 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3454 00001DDC 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3455 00001DDE E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3456                              <1> CHK_RET:
  3457 00001DE3 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3458                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3459 00001DE8 58                  <1> 	pop	eax ; 24/12/2021
  3460 00001DE9 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3461 00001DEB E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3462                              <1> RWV_END:
  3463 00001DF0 E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3464 00001DF5 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3465                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3466                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3467 00001DFA 50                  <1> 	push	eax ; 24/12/2021
  3468 00001DFB E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3469                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3470 00001E00 58                  <1> 	pop	eax ; 24/12/2021
  3471 00001E01 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3472 00001E06 C3                  <1> 	RETn
  3473                              <1> 
  3474                              <1> ;-------------------------------------------------------------------------------
  3475                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3476                              <1> ;-------------------------------------------------------------------------------
  3477                              <1> SETUP_STATE:
  3478 00001E07 F687[D96B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3479 00001E0E 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3480 00001E10 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3481 00001E14 F687[D96B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3482 00001E1B 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3483 00001E1D F687[D96B0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3484 00001E24 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3485 00001E26 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3486                              <1> AX_SET:	
  3487 00001E2A 80A7[D96B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3488 00001E31 08A7[D96B0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3489 00001E37 8025[D46B0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3490 00001E3E C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3491 00001E41 0805[D46B0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3492                              <1> J1C:	
  3493 00001E47 C3                  <1> 	RETn
  3494                              <1> 
  3495                              <1> ;-------------------------------------------------------------------------------
  3496                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3497                              <1> ;-------------------------------------------------------------------------------
  3498                              <1> FMT_INIT:
  3499 00001E48 F687[D96B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3500 00001E4F 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3501 00001E51 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3502                              <1> 	;; 20/02/2015
  3503                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3504 00001E56 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3505 00001E58 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3506                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3507 00001E5A 8AA7[D96B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3508 00001E60 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3509 00001E63 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3510 00001E65 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3511 00001E67 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3512 00001E6A EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3513                              <1> N_360:	
  3514 00001E6C FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3515 00001E6E 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3516                              <1> F1_RATE:
  3517 00001E70 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3518 00001E73 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3519                              <1> N_12:	
  3520 00001E75 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3521 00001E77 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3522 00001E79 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3523 00001E7C 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3524 00001E7E F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3525 00001E81 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3526 00001E83 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3527 00001E86 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3528                              <1> N_720:
  3529 00001E88 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3530 00001E8A 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3531 00001E8C EBE2                <1> 	JMP	SHORT F1_RATE
  3532                              <1> ISNT_12: 
  3533 00001E8E 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3534                              <1> 
  3535                              <1> SKP_STATE:
  3536 00001E91 88A7[D96B0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3537                              <1> F1_OUT:
  3538 00001E97 C3                  <1> 	RETn
  3539                              <1> CL_DRV:	
  3540 00001E98 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3541 00001E9A EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3542                              <1> 
  3543                              <1> ;-------------------------------------------------------------------------------
  3544                              <1> ; MED_CHANGE	
  3545                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3546                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3547                              <1> ;
  3548                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3549                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3550                              <1> ;-------------------------------------------------------------------------------
  3551                              <1> MED_CHANGE:
  3552 00001E9C E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3553 00001EA1 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3554 00001EA3 80A7[D96B0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3555                              <1> 
  3556                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3557                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3558                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3559                              <1> 
  3560 00001EAA 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3561 00001EAD B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3562 00001EAF D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3563 00001EB1 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3564 00001EB3 FA                  <1> 	CLI				; NO INTERRUPTS
  3565 00001EB4 2005[CA6B0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3566 00001EBA FB                  <1> 	STI				; INTERRUPTS ENABLED
  3567 00001EBB E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3568                              <1> 
  3569                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3570                              <1> 
  3571 00001EC0 E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3572 00001EC5 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3573 00001EC7 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3574 00001ECC 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3575 00001ECE E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3576 00001ED3 C605[CC6B0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3577                              <1> OK1:
  3578 00001EDA E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3579 00001EDF 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3580                              <1> OK4:
  3581 00001EE1 C605[CC6B0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3582                              <1> OK2:		
  3583 00001EE8 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3584 00001EE9 C3                  <1> 	RETn
  3585                              <1> MC_OUT:
  3586 00001EEA F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3587 00001EEB C3                  <1> 	RETn
  3588                              <1> 
  3589                              <1> ;-------------------------------------------------------------------------------
  3590                              <1> ; SEND_RATE
  3591                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3592                              <1> ; ON ENTRY:	DI = DRIVE #
  3593                              <1> ; ON EXIT:	NONE
  3594                              <1> ; REGISTERS ALTERED: DX
  3595                              <1> ;-------------------------------------------------------------------------------
  3596                              <1> SEND_RATE:
  3597                              <1> 	;PUSH	AX			; SAVE REG.
  3598                              <1> 	; 24/12/2021
  3599 00001EEC 50                  <1> 	push	eax
  3600 00001EED 8025[D46B0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3601 00001EF4 8A87[D96B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3602 00001EFA 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3603 00001EFC 0805[D46B0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3604 00001F02 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3605 00001F05 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3606 00001F09 EE                  <1> 	OUT	DX,AL
  3607                              <1> 	;POP	AX			; RESTORE REG.
  3608                              <1> 	; 24/12/2021
  3609 00001F0A 58                  <1> 	pop	eax
  3610 00001F0B C3                  <1> 	RETn
  3611                              <1> 
  3612                              <1> ;-------------------------------------------------------------------------------
  3613                              <1> ; CHK_LASTRATE
  3614                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3615                              <1> ; ON ENTRY:
  3616                              <1> ;	DI = DRIVE #
  3617                              <1> ; ON EXIT:
  3618                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3619                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3620                              <1> ; REGISTERS ALTERED: DX
  3621                              <1> ;-------------------------------------------------------------------------------
  3622                              <1> CHK_LASTRATE:
  3623                              <1> 	;PUSH	AX			; SAVE REG.
  3624                              <1> 	; 24/12/2021
  3625 00001F0C 50                  <1> 	push	eax
  3626 00001F0D 2225[D46B0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3627 00001F13 8A87[D96B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3628 00001F19 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3629 00001F1D 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3630                              <1> 					; ZF = 1 RATE IS THE SAME
  3631                              <1> 	;POP	AX			; RESTORE REG.
  3632                              <1> 	; 24/12/2021
  3633 00001F1F 58                  <1> 	pop	eax
  3634 00001F20 C3                  <1> 	RETn
  3635                              <1> 
  3636                              <1> ;-------------------------------------------------------------------------------
  3637                              <1> ; DMA_SETUP
  3638                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3639                              <1> ;
  3640                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3641                              <1> ;
  3642                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3643                              <1> ;-------------------------------------------------------------------------------
  3644                              <1> 
  3645                              <1> ; SI = Head #, # of Sectors or DASD Type
  3646                              <1> 
  3647                              <1> ; 22/08/2015
  3648                              <1> ; 08/02/2015 - Protected Mode Modification
  3649                              <1> ; 06/02/2015 - 07/02/2015
  3650                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3651                              <1> ; (DMA Addres = Physical Address)
  3652                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3653                              <1> ;
  3654                              <1> ; 04/02/2016 (clc)
  3655                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3656                              <1> ; 16/12/2014 (IODELAY)
  3657                              <1> 
  3658                              <1> DMA_SETUP:
  3659                              <1> 
  3660                              <1> ;; 20/02/2015
  3661 00001F21 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3662 00001F24 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3663 00001F2A 7569                <1> 	jnz	short dma_bnd_err_stc
  3664                              <1> 	;
  3665                              <1> 	;push	ax			; DMA command
  3666                              <1> 	; 24/12/2021
  3667 00001F2C 50                  <1> 	push	eax
  3668 00001F2D 52                  <1> 	push	edx			; *
  3669 00001F2E B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3670 00001F30 E840030000          <1> 	call	GET_PARM		; 
  3671 00001F35 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3672                              <1> 	;mov	ax, si			; Sector count
  3673                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3674                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3675                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3676                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3677                              <1> 	; 24/12/2021
  3678 00001F37 89F2                <1> 	mov	edx, esi
  3679 00001F39 29C0                <1> 	sub	eax, eax
  3680 00001F3B 88D4                <1> 	mov	ah, dl
  3681 00001F3D D1E8                <1> 	shr	eax, 1
  3682 00001F3F D3E0                <1> 	shl	eax, cl
  3683                              <1> 	;
  3684 00001F41 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3685 00001F43 6689C1              <1> 	mov	cx, ax
  3686 00001F46 5A                  <1> 	pop	edx			; *
  3687                              <1> 	;pop	ax
  3688                              <1> 	; 24/12/2021
  3689 00001F47 58                  <1> 	pop	eax
  3690 00001F48 3C42                <1> 	cmp	al, 42h
  3691 00001F4A 7507                <1>         jne     short NOT_VERF
  3692 00001F4C BA0000FF00          <1> 	mov	edx, 0FF0000h
  3693 00001F51 EB08                <1> 	jmp	short J33
  3694                              <1> NOT_VERF:
  3695 00001F53 6601CA              <1> 	add	dx, cx			; check for overflow
  3696 00001F56 723E                <1> 	jc	short dma_bnd_err
  3697                              <1> 	;
  3698 00001F58 6629CA              <1> 	sub	dx, cx			; Restore start address
  3699                              <1> J33:
  3700 00001F5B FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3701 00001F5C E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3702                              <1> 	IODELAY				; WAIT FOR I/O
  2044 00001F5E EB00                <2>  jmp short $+2
  2045 00001F60 EB00                <2>  jmp short $+2
  3703 00001F62 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3704 00001F64 89D0                <1> 	mov	eax,edx			; Buffer address
  3705 00001F66 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3706                              <1> 	IODELAY				; WAIT FOR I/O
  2044 00001F68 EB00                <2>  jmp short $+2
  2045 00001F6A EB00                <2>  jmp short $+2
  3707 00001F6C 88E0                <1> 	MOV	AL,AH
  3708 00001F6E E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3709 00001F70 C1E810              <1> 	shr	eax,16
  3710                              <1> 	IODELAY				; I/O WAIT STATE
  2044 00001F73 EB00                <2>  jmp short $+2
  2045 00001F75 EB00                <2>  jmp short $+2
  3711 00001F77 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3712                              <1> 	IODELAY
  2044 00001F79 EB00                <2>  jmp short $+2
  2045 00001F7B EB00                <2>  jmp short $+2
  3713 00001F7D 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3714 00001F80 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3715                              <1> 	IODELAY				; WAIT FOR I/O
  2044 00001F82 EB00                <2>  jmp short $+2
  2045 00001F84 EB00                <2>  jmp short $+2
  3716 00001F86 88E0                <1> 	MOV	AL,AH
  3717 00001F88 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3718                              <1> 	IODELAY
  2044 00001F8A EB00                <2>  jmp short $+2
  2045 00001F8C EB00                <2>  jmp short $+2
  3719 00001F8E FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3720 00001F8F B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3721 00001F91 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3722                              <1> 
  3723 00001F93 F8                  <1> 	clc	; 04/02/2016
  3724 00001F94 C3                  <1> 	retn
  3725                              <1> 
  3726                              <1> dma_bnd_err_stc:
  3727 00001F95 F9                  <1> 	stc
  3728                              <1> dma_bnd_err:
  3729 00001F96 C605[CC6B0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3730 00001F9D C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3731                              <1> 
  3732                              <1> ;; 16/12/2014
  3733                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3734                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3735                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3736                              <1> ;;	IODELAY
  3737                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3738                              <1> ;;	;SIODELAY
  3739                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3740                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3741                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3742                              <1> ;;      ;JMP	SHORT J33
  3743                              <1> ;;;NOT_VERF:	
  3744                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3745                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3746                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3747                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3748                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3749                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3750                              <1> ;;	;JNC	short J33
  3751                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3752                              <1> ;;;J33:
  3753                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3754                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3755                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3756                              <1> ;;	IODELAY
  3757                              <1> ;;	MOV	AL,AH
  3758                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3759                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3760                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3761                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3762                              <1> ;;	IODELAY
  3763                              <1> ;;	;AND	AL,00001111B
  3764                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3765                              <1> ;;	;SIODELAY
  3766                              <1> ;;
  3767                              <1> ;;;----- DETERMINE COUNT
  3768                              <1> ;;	sub	eax, eax ; 08/02/2015
  3769                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3770                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3771                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3772                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3773                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3774                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3775                              <1> ;;	CALL	GET_PARM		; "
  3776                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3777                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3778                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3779                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3780                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3781                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3782                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3783                              <1> ;;	IODELAY
  3784                              <1> ;;	MOV	AL, AH
  3785                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3786                              <1> ;;	;IODELAY
  3787                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3788                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3789                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3790                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3791                              <1> ;;	add	ecx, eax ; 08/02/2015
  3792                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3793                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3794                              <1> ;;	SIODELAY
  3795                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3796                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3797                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3798                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3799                              <1> ;;	jz	short NO_BAD
  3800                              <1> ;;dma_bnd_err:
  3801                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3802                              <1> ;;NO_BAD:
  3803                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3804                              <1> 
  3805                              <1> ;-------------------------------------------------------------------------------
  3806                              <1> ; FMTDMA_SET
  3807                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3808                              <1> ;
  3809                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3810                              <1> ;
  3811                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3812                              <1> ;-------------------------------------------------------------------------------
  3813                              <1> 
  3814                              <1> 	; 24/12/2021
  3815                              <1> FMTDMA_SET:
  3816                              <1> ;; 20/02/2015 modification	
  3817 00001F9E 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3818 00001FA1 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3819 00001FA7 75EC                <1> 	jnz	short dma_bnd_err_stc
  3820                              <1> 	;
  3821                              <1> 	;push	dx			; *
  3822                              <1> 	; 24/12/2021
  3823 00001FA9 52                  <1> 	push	edx
  3824 00001FAA B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3825 00001FAC E8C4020000          <1> 	call	GET_PARM		; "
  3826                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3827                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3828                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3829                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3830                              <1> 	;mov	cx, ax
  3831                              <1> 	; 24/12/2021
  3832 00001FB1 29C9                <1> 	sub	ecx, ecx
  3833 00001FB3 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3834 00001FB5 D1E1                <1> 	shl	ecx, 1
  3835 00001FB7 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3836 00001FB9 6649                <1> 	dec	cx
  3837                              <1> 	;pop	dx			; *
  3838                              <1> 	; 24/12/2021
  3839 00001FBB 5A                  <1> 	pop	edx
  3840 00001FBC 6601CA              <1> 	add	dx, cx			; check for overflow
  3841 00001FBF 72D5                <1> 	jc	short dma_bnd_err
  3842                              <1> 	;
  3843 00001FC1 6629CA              <1> 	sub	dx, cx			; Restore start address
  3844                              <1> 	;
  3845 00001FC4 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3846 00001FC6 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3847 00001FC7 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3848                              <1> 	IODELAY				; WAIT FOR I/O
  2044 00001FC9 EB00                <2>  jmp short $+2
  2045 00001FCB EB00                <2>  jmp short $+2
  3849 00001FCD E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3850 00001FCF 89D0                <1> 	mov	eax,edx			; Buffer address
  3851 00001FD1 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3852                              <1> 	IODELAY				; WAIT FOR I/O
  2044 00001FD3 EB00                <2>  jmp short $+2
  2045 00001FD5 EB00                <2>  jmp short $+2
  3853 00001FD7 88E0                <1> 	MOV	AL,AH
  3854 00001FD9 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3855 00001FDB C1E810              <1> 	shr	eax,16
  3856                              <1> 	IODELAY				; I/O WAIT STATE
  2044 00001FDE EB00                <2>  jmp short $+2
  2045 00001FE0 EB00                <2>  jmp short $+2
  3857 00001FE2 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3858                              <1> 	IODELAY
  2044 00001FE4 EB00                <2>  jmp short $+2
  2045 00001FE6 EB00                <2>  jmp short $+2
  3859 00001FE8 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3860 00001FEB E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3861                              <1> 	IODELAY				; WAIT FOR I/O
  2044 00001FED EB00                <2>  jmp short $+2
  2045 00001FEF EB00                <2>  jmp short $+2
  3862 00001FF1 88E0                <1> 	MOV	AL,AH
  3863 00001FF3 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3864                              <1> 	IODELAY
  2044 00001FF5 EB00                <2>  jmp short $+2
  2045 00001FF7 EB00                <2>  jmp short $+2
  3865 00001FF9 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3866 00001FFA B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3867 00001FFC E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3868 00001FFE C3                  <1> 	retn
  3869                              <1> 
  3870                              <1> ;; 08/02/2015 - Protected Mode Modification
  3871                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3872                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3873                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3874                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3875                              <1> ;;	IODELAY
  3876                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3877                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3878                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3879                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3880                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3881                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3882                              <1> ;;	;JNC	short J33A
  3883                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3884                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3885                              <1> ;;;J33A:
  3886                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3887                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3888                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3889                              <1> ;;	IODELAY
  3890                              <1> ;;	MOV	AL,AH
  3891                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3892                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3893                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3894                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3895                              <1> ;;	IODELAY
  3896                              <1> ;;	;AND	AL,00001111B
  3897                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3898                              <1> ;;
  3899                              <1> ;;;----- DETERMINE COUNT
  3900                              <1> ;;	sub	eax, eax ; 08/02/2015
  3901                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3902                              <1> ;;	CALL	GET_PARM		; "
  3903                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3904                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3905                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3906                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3907                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3908                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3909                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3910                              <1> ;;	IODELAY
  3911                              <1> ;;	MOV	AL, AH
  3912                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3913                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3914                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  3915                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  3916                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3917                              <1> ;;	add	ecx, eax ; 08/02/2015
  3918                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3919                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3920                              <1> ;;	SIODELAY
  3921                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3922                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  3923                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  3924                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  3925                              <1> ;;	jz	short FMTDMA_OK
  3926                              <1> ;;	stc	; 20/02/2015
  3927                              <1> ;;fmtdma_bnd_err:
  3928                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3929                              <1> ;;FMTDMA_OK:
  3930                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3931                              <1> 
  3932                              <1> ;-------------------------------------------------------------------------------
  3933                              <1> ; NEC_INIT	
  3934                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3935                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3936                              <1> ;
  3937                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3938                              <1> ;
  3939                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3940                              <1> ;-------------------------------------------------------------------------------
  3941                              <1> NEC_INIT:
  3942                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3943                              <1> 	; 24/12/2021
  3944 00001FFF 50                  <1> 	push	eax
  3945 00002000 E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3946                              <1> 
  3947                              <1> ;-----	DO THE SEEK OPERATION
  3948                              <1> 
  3949 00002005 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  3950 00002008 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  3951                              <1> 	;POP	AX			; RECOVER COMMAND
  3952                              <1> 	; 24/12/2021
  3953 0000200D 58                  <1> 	pop	eax
  3954 0000200E 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  3955 00002010 BB[2E200000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  3956 00002015 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  3957                              <1> 
  3958                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3959                              <1> 
  3960 00002016 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3961 0000201B 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  3962 0000201E 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  3963 00002020 C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  3964 00002023 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  3965 00002026 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  3966 00002028 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3967 0000202D 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  3968                              <1> ER_1:
  3969 0000202E C3                  <1> 	RETn
  3970                              <1> 
  3971                              <1> ;-------------------------------------------------------------------------------
  3972                              <1> ; RWV_COM
  3973                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3974                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3975                              <1> ;
  3976                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3977                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3978                              <1> ;-------------------------------------------------------------------------------
  3979                              <1> RWV_COM:
  3980 0000202F B8[7A200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  3981 00002034 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3982 00002035 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  3983 00002038 E83E030000          <1> 	CALL	NEC_OUTPUT
  3984 0000203D 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  3985 00002040 E836030000          <1> 	CALL	NEC_OUTPUT
  3986 00002045 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  3987 00002048 E82E030000          <1> 	CALL	NEC_OUTPUT
  3988 0000204D B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3989 0000204F E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  3990 00002054 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3991 00002059 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  3992 0000205B E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  3993 00002060 E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3994 00002065 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  3995                              <1> _R15:
  3996 00002068 E80E030000          <1> 	CALL	NEC_OUTPUT
  3997 0000206D B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  3998 0000206F E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  3999 00002074 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4000 00002079 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4001                              <1> ER_2:
  4002 0000207A C3                  <1> 	RETn
  4003                              <1> 
  4004                              <1> ;-------------------------------------------------------------------------------
  4005                              <1> ; NEC_TERM
  4006                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4007                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4008                              <1> ;
  4009                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4010                              <1> ;-------------------------------------------------------------------------------
  4011                              <1> NEC_TERM:
  4012                              <1> 
  4013                              <1> ;-----	LET THE OPERATION HAPPEN
  4014                              <1> 
  4015 0000207B 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4016 0000207C E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4017 00002081 9C                  <1> 	PUSHFd	; 24/12/2021
  4018 00002082 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4019 00002087 724B                <1> 	JC	short SET_END_POP
  4020 00002089 9D                  <1> 	POPFd	; 24/12/2021
  4021 0000208A 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4022                              <1> 
  4023                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4024                              <1> 
  4025 0000208C FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4026 0000208D BE[CD6B0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4027 00002092 AC                  <1> 	lodsb				; GET ST0
  4028 00002093 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4029 00002095 7433                <1> 	JZ	short SET_END
  4030 00002097 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4031 00002099 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4032                              <1> 
  4033                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4034                              <1> 
  4035 0000209B AC                  <1> 	lodsb				; GET ST1
  4036 0000209C D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4037 0000209E B404                <1> 	MOV	AH,RECORD_NOT_FND
  4038 000020A0 7222                <1> 	JC	short J19
  4039 000020A2 C0E002              <1> 	SAL	AL,2
  4040 000020A5 B410                <1> 	MOV	AH,BAD_CRC
  4041 000020A7 721B                <1> 	JC	short J19
  4042 000020A9 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4043 000020AB B408                <1> 	MOV	AH,BAD_DMA
  4044 000020AD 7215                <1> 	JC	short J19
  4045 000020AF C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4046 000020B2 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4047 000020B4 720E                <1> 	JC	short J19
  4048 000020B6 D0E0                <1> 	SAL	AL,1
  4049 000020B8 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4050 000020BA 7208                <1> 	JC	short J19
  4051 000020BC D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4052 000020BE B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4053 000020C0 7202                <1> 	JC	short J19
  4054                              <1> 
  4055                              <1> ;----- 	NEC MUST HAVE FAILED
  4056                              <1> J18:
  4057 000020C2 B420                <1> 	MOV	AH,BAD_NEC
  4058                              <1> J19:
  4059 000020C4 0825[CC6B0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4060                              <1> SET_END:
  4061 000020CA 803D[CC6B0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4062 000020D1 F5                  <1> 	CMC
  4063 000020D2 5E                  <1> 	POP	eSI
  4064 000020D3 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4065                              <1> 
  4066                              <1> SET_END_POP:
  4067 000020D4 9D                  <1> 	POPFd	; 24/12/2021
  4068 000020D5 EBF3                <1> 	JMP	SHORT SET_END
  4069                              <1> 
  4070                              <1> ;-------------------------------------------------------------------------------
  4071                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4072                              <1> ;-------------------------------------------------------------------------------
  4073                              <1> DSTATE:
  4074 000020D7 803D[CC6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4075 000020DE 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4076 000020E0 808F[D96B0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4077 000020E7 F687[D96B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4078 000020EE 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4079 000020F0 8A87[D96B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4080 000020F6 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4081 000020F8 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4082 000020FA 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4083                              <1> 
  4084                              <1> ;----- 	CHECK IF IT IS 1.44M
  4085                              <1> 
  4086 000020FC E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4087                              <1> 	;;20/02/2015
  4088                              <1> 	;;JC	short M_12		; CMOS BAD
  4089 00002101 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4090 00002103 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4091 00002105 7410                <1> 	JE	short M_12		; YES
  4092                              <1> M_720:
  4093 00002107 80A7[D96B0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4094 0000210E 808F[D96B0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4095 00002115 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4096                              <1> M_12:	
  4097 00002117 808F[D96B0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4098                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4099                              <1> SETBAC:
  4100 0000211E C3                  <1> 	RETn
  4101                              <1> 
  4102                              <1> ;-------------------------------------------------------------------------------
  4103                              <1> ; RETRY	
  4104                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4105                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4106                              <1> ;
  4107                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4108                              <1> ;-------------------------------------------------------------------------------
  4109                              <1> RETRY:
  4110 0000211F 803D[CC6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4111 00002126 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4112 00002128 803D[CC6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4113 0000212F 743C                <1> 	JZ	short NO_RETRY
  4114 00002131 8AA7[D96B0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4115 00002137 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4116 0000213A 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4117 0000213C 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4118 0000213F 8A2D[D46B0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4119 00002145 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4120 00002148 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4121 0000214B 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4122 0000214D 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4123                              <1> 
  4124                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4125                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4126                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4127                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4128                              <1> 
  4129 0000214F 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4130 00002152 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4131 00002154 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4132 00002157 80A7[D96B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4133                              <1> 					; RATE, DBL STEP OFF
  4134 0000215E 08A7[D96B0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4135 00002164 C605[CC6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4136 0000216B F9                  <1> 	STC				; SET CARRY FOR RETRY
  4137 0000216C C3                  <1> 	RETn				; RETRY RETURN
  4138                              <1> 
  4139                              <1> NO_RETRY:
  4140 0000216D F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4141 0000216E C3                  <1> 	RETn				; NO RETRY RETURN
  4142                              <1> 
  4143                              <1> ;-------------------------------------------------------------------------------
  4144                              <1> ; NUM_TRANS
  4145                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4146                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4147                              <1> ;
  4148                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4149                              <1> ;		SI-HI  = HEAD
  4150                              <1> ;		[BP]   = START SECTOR
  4151                              <1> ;
  4152                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4153                              <1> ;-------------------------------------------------------------------------------
  4154                              <1> NUM_TRANS:
  4155 0000216F 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4156 00002171 803D[CC6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4157                              <1> 	; 24/12/2021
  4158 00002178 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4159 0000217A B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4160 0000217C E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4161 00002181 8A1D[D26B0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4162 00002187 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4163 0000218A 3A2D[D16B0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4164 00002190 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4165 00002192 8A2D[D06B0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4166 00002198 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4167 0000219B 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4168 0000219D 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4169                              <1> DIF_HD:
  4170 0000219F 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4171                              <1> SAME_TRK:
  4172 000021A1 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4173 000021A4 88D8                <1> 	MOV	AL,BL			; TO AL
  4174                              <1> NT_OUT:
  4175 000021A6 C3                  <1> 	RETn
  4176                              <1> 
  4177                              <1> ;-------------------------------------------------------------------------------
  4178                              <1> ; SETUP_END
  4179                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4180                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4181                              <1> ;
  4182                              <1> ; ON EXIT:
  4183                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4184                              <1> ;-------------------------------------------------------------------------------
  4185                              <1> SETUP_END:
  4186 000021A7 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4187                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4188 000021A9 50                  <1> 	push	eax ; 24/12/2021
  4189 000021AA E8C6000000          <1> 	CALL	GET_PARM
  4190 000021AF 8825[CB6B0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4191                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4192 000021B5 58                  <1> 	pop	eax ; 24/12/2021
  4193 000021B6 8A25[CC6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4194 000021BC 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4195 000021BE 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4196 000021C0 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4197                              <1> NUN_ERR: 
  4198 000021C2 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4199 000021C5 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4200 000021C6 C3                  <1> 	RETn
  4201                              <1> 
  4202                              <1> ;-------------------------------------------------------------------------------
  4203                              <1> ; SETUP_DBL
  4204                              <1> ;	CHECK DOUBLE STEP.
  4205                              <1> ;
  4206                              <1> ; ON ENTRY :	DI = DRIVE
  4207                              <1> ;
  4208                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4209                              <1> ;-------------------------------------------------------------------------------
  4210                              <1> SETUP_DBL:
  4211 000021C7 8AA7[D96B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4212 000021CD F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4213 000021D0 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4214                              <1> 
  4215                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4216                              <1> 
  4217 000021D2 C605[C96B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4218 000021D9 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4219 000021DE B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4220 000021E0 E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4221 000021E5 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4222 000021EA 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4223                              <1> 
  4224                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4225                              <1> 
  4226 000021EC 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4227 000021F0 F687[D96B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4228 000021F7 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4229 000021F9 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4230                              <1> 
  4231                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4232                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4233                              <1> ;	THEN SET DOUBLE STEP ON.
  4234                              <1> 
  4235                              <1> CNT_OK:
  4236 000021FB C605[CB6B0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4237                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4238                              <1> 	; 24/12/2021
  4239 00002202 51                  <1> 	push	ecx
  4240 00002203 C605[CC6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4241 0000220A 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4242 0000220D D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4243 0000220F C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4244                              <1> 	;PUSH	AX			; SAVE HEAD
  4245                              <1> 	; 24/12/2021
  4246 00002212 50                  <1> 	push	eax
  4247 00002213 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4248                              <1> 	;POP	AX			; RESTORE HEAD
  4249                              <1> 	; 24/12/2021
  4250 00002218 58                  <1> 	pop	eax
  4251 00002219 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4252 0000221C E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4253 00002221 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4254 00002222 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4255 00002227 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4256                              <1> 	;POP	CX			; RESTORE COUNT
  4257                              <1> 	; 24/12/2021
  4258 00002228 59                  <1> 	pop	ecx
  4259 00002229 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4260 0000222B FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4261 0000222D 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4262 0000222F 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4263                              <1> 
  4264                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4265                              <1> 
  4266                              <1> SD_ERR:	
  4267 00002231 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4268 00002232 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4269                              <1> 
  4270                              <1> DO_CHK:
  4271 00002233 8A0D[D06B0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4272 00002239 888F[DD6B0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4273 0000223F D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4274 00002241 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4275 00002243 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4276 00002245 808F[D96B0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4277                              <1> NO_DBL:
  4278 0000224C F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4279 0000224D C3                  <1> 	RETn
  4280                              <1> 
  4281                              <1> ;-------------------------------------------------------------------------------
  4282                              <1> ; READ_ID
  4283                              <1> ;	READ ID FUNCTION.
  4284                              <1> ;
  4285                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4286                              <1> ;
  4287                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4288                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4289                              <1> ;-------------------------------------------------------------------------------
  4290                              <1> READ_ID:
  4291 0000224E B8[6B220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4292 00002253 50                  <1> 	PUSH	eAX
  4293 00002254 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4294 00002256 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4295 0000225B 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4296 0000225E 88C4                <1> 	MOV	AH,AL
  4297 00002260 E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4298 00002265 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4299 0000226A 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4300                              <1> ER_3:
  4301 0000226B C3                  <1> 	RETn
  4302                              <1> 
  4303                              <1> ;-------------------------------------------------------------------------------
  4304                              <1> ; CMOS_TYPE
  4305                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4306                              <1> ;
  4307                              <1> ; ON ENTRY:	DI = DRIVE #
  4308                              <1> ;
  4309                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4310                              <1> ;-------------------------------------------------------------------------------
  4311                              <1> 
  4312                              <1> CMOS_TYPE: ; 11/12/2014
  4313 0000226C 8A87[3E660000]      <1> 	mov	al, [eDI+fd0_type]
  4314 00002272 20C0                <1> 	and 	al, al ; 18/12/2014
  4315 00002274 C3                  <1> 	retn
  4316                              <1> 
  4317                              <1> ;CMOS_TYPE:
  4318                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4319                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4320                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4321                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4322                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4323                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4324                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4325                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4326                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4327                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4328                              <1> ;TB:
  4329                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4330                              <1> ;BAD_CM:
  4331                              <1> ;	RETn				; CY, STATUS OF READ
  4332                              <1> 
  4333                              <1> ;-------------------------------------------------------------------------------
  4334                              <1> ; GET_PARM
  4335                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4336                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4337                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4338                              <1> ;	THE PARAMETER IN DL.
  4339                              <1> ;
  4340                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4341                              <1> ;
  4342                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4343                              <1> ;		AL,DH DESTROYED
  4344                              <1> ;-------------------------------------------------------------------------------
  4345                              <1> GET_PARM:
  4346                              <1> 	;PUSH	DS
  4347 00002275 56                  <1> 	PUSH	eSI
  4348                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4349                              <1>     	;MOV	DS,AX
  4350                              <1> 	;;mov	ax, cs
  4351                              <1> 	;;mov	ds, ax
  4352                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4353 00002276 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4354                              <1> 	;SUB	BH,BH			; BX = INDEX
  4355 00002278 81E3FF000000        <1> 	and	ebx, 0FFh
  4356                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4357                              <1> 	;
  4358                              <1> 	; 17/12/2014
  4359 0000227E 66A1[31660000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4360 00002284 38E0                <1> 	cmp	al, ah
  4361 00002286 7425                <1> 	je	short gpndc
  4362 00002288 A2[32660000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4363 0000228D 53                  <1> 	push	ebx ; 08/02/2015
  4364 0000228E 88C3                <1> 	mov	bl, al 
  4365                              <1> 	; 11/12/2014
  4366 00002290 8A83[3E660000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4367                              <1> 	; 18/12/2014
  4368 00002296 20C0                <1> 	and	al, al
  4369 00002298 7507                <1> 	jnz	short gpdtc
  4370 0000229A BB[1B660000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4371 0000229F EB05                <1>         jmp     short gpdpu
  4372                              <1> gpdtc:	
  4373 000022A1 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4374                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4375                              <1> gpdpu:
  4376 000022A6 891D[B8650000]      <1> 	mov	[DISK_POINTER], ebx
  4377 000022AC 5B                  <1> 	pop	ebx
  4378                              <1> gpndc:
  4379 000022AD 8B35[B8650000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4380 000022B3 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4381 000022B6 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4382 000022B8 5E                  <1> 	POP	eSI
  4383                              <1> 	;POP	DS
  4384 000022B9 C3                  <1> 	RETn
  4385                              <1> 
  4386                              <1> ;-------------------------------------------------------------------------------
  4387                              <1> ; MOTOR_ON
  4388                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4389                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4390                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4391                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4392                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4393                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4394                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4395                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4396                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4397                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4398                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4399                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4400                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4401                              <1> ;
  4402                              <1> ; ON ENTRY:	DI = DRIVE #
  4403                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4404                              <1> ;-------------------------------------------------------------------------------
  4405                              <1> MOTOR_ON:
  4406 000022BA 53                  <1> 	PUSH	eBX			; SAVE REG.
  4407 000022BB E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4408 000022C0 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4409 000022C2 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4410 000022C7 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4411                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4412                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4413                              <1> M_WAIT:
  4414 000022CC B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4415 000022CE E8A2FFFFFF          <1> 	CALL	GET_PARM
  4416                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4417                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4418                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4419 000022D3 80FC08              <1> 	cmp	ah, 8
  4420                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4421 000022D6 7702                <1> 	ja	short J13
  4422                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4423 000022D8 B408                <1> 	mov	ah, 8
  4424                              <1> 
  4425                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4426                              <1> GP2:	
  4427                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4428                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4429 000022DA B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4430 000022DF E806F2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4431                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4432 000022E4 FECC                <1> 	dec	ah
  4433 000022E6 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4434                              <1> MOT_IS_ON:
  4435 000022E8 5B                  <1> 	POP	eBX			; RESTORE REG.
  4436 000022E9 C3                  <1> 	RETn
  4437                              <1> 
  4438                              <1> ;-------------------------------------------------------------------------------
  4439                              <1> ; TURN_ON
  4440                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4441                              <1> ;
  4442                              <1> ; ON ENTRY:	DI = DRIVE #
  4443                              <1> ;
  4444                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4445                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4446                              <1> ;		AX,BX,CX,DX DESTROYED
  4447                              <1> ;-------------------------------------------------------------------------------
  4448                              <1> TURN_ON:
  4449 000022EA 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4450 000022EC 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4451 000022EE C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4452 000022F1 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4453 000022F2 C605[CB6B0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4454 000022F9 A0[CA6B0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4455 000022FE 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4456 00002300 B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4457 00002302 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4458                              <1> 
  4459                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4460                              <1> ;  BL = DRIVE SELECT DESIRED
  4461                              <1> ;  AH = MOTOR ON MASK DESIRED
  4462                              <1> 
  4463 00002304 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4464 00002306 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4465 00002308 8425[CA6B0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4466 0000230E 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4467                              <1> 
  4468                              <1> TURN_IT_ON:
  4469 00002310 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4470 00002312 8A3D[CA6B0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4471 00002318 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4472 0000231B 8025[CA6B0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4473 00002322 0825[CA6B0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4474 00002328 A0[CA6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4475 0000232D 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4476 0000232F 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4477 00002332 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4478 00002333 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4479 00002335 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4480 00002338 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4481 0000233A 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4482 0000233E EE                  <1> 	OUT	DX,AL
  4483 0000233F 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4484                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4485 00002341 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4486 00002343 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4487 00002344 C3                  <1> 	RETn
  4488                              <1> 
  4489                              <1> NO_MOT_WAIT:
  4490 00002345 FB                  <1> 	sti
  4491                              <1> no_mot_w1: ; 27/02/2015
  4492 00002346 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4493                              <1> 	;STI				; INTERRUPTS BACK ON
  4494 00002347 C3                  <1> 	RETn
  4495                              <1> 
  4496                              <1> ;-------------------------------------------------------------------------------
  4497                              <1> ; HD_WAIT
  4498                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4499                              <1> ;
  4500                              <1> ; ON ENTRY:	DI = DRIVE #
  4501                              <1> ;
  4502                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4503                              <1> ;-------------------------------------------------------------------------------
  4504                              <1> HD_WAIT:
  4505 00002348 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4506 0000234A E826FFFFFF          <1> 	CALL	GET_PARM
  4507 0000234F 08E4                <1> 	or	ah, ah	; 17/12/2014
  4508 00002351 7519                <1> 	jnz	short DO_WAT
  4509 00002353 F605[CA6B0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4510                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4511                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4512                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4513 0000235A 741E                <1> 	jz	short HW_DONE
  4514 0000235C B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4515 0000235E 8A87[D96B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4516 00002364 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4517 00002366 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4518 00002368 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4519                              <1> ;GP3:
  4520 0000236A B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4521                              <1> ;	JMP	SHORT DO_WAT
  4522                              <1> 
  4523                              <1> ;ISNT_WRITE:
  4524                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4525                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4526                              <1> 
  4527                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4528                              <1> DO_WAT:
  4529                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4530                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4531                              <1> J29:					; 	1 MILLISECOND LOOP
  4532                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4533 0000236C B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4534 00002371 E874F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4535                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4536 00002376 FECC                <1> 	dec	ah
  4537 00002378 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4538                              <1> HW_DONE:
  4539 0000237A C3                  <1> 	RETn
  4540                              <1> 
  4541                              <1> ;-------------------------------------------------------------------------------
  4542                              <1> ; NEC_OUTPUT
  4543                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4544                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4545                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4546                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4547                              <1> ; 
  4548                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4549                              <1> ;
  4550                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4551                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4552                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4553                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4554                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4555                              <1> ;		AX,CX,DX DESTROYED
  4556                              <1> ;-------------------------------------------------------------------------------
  4557                              <1> 
  4558                              <1> ; 09/12/2014 [Erdogan Tan] 
  4559                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4560                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4561                              <1> ;	This read only register facilitates the transfer of data between
  4562                              <1> ;	the system microprocessor and the controller.
  4563                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4564                              <1> ;	  with the system micrprocessor.
  4565                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4566                              <1> ;	  the transfer is to the controller.
  4567                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4568                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4569                              <1> ; Bit 3 - Reserved.
  4570                              <1> ; Bit 2 - Reserved.
  4571                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4572                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4573                              <1> 
  4574                              <1> ; Data Register (3F5h)
  4575                              <1> ; This read/write register passes data, commands and parameters, and provides
  4576                              <1> ; diskette status information.
  4577                              <1>   		
  4578                              <1> NEC_OUTPUT:
  4579                              <1> 	;PUSH	BX			; SAVE REG.
  4580 0000237B 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4581                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4582                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4583                              <1> 	; 16/12/2014
  4584                              <1> 	; waiting for (max.) 0.5 seconds
  4585                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4586                              <1> 	;
  4587                              <1> 	; 17/12/2014
  4588                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4589                              <1> 	;
  4590                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4591                              <1> 	;		go on.
  4592                              <1> 	;INPUT:
  4593                              <1> 	;	AH=Mask for isolation bits.
  4594                              <1> 	;	AL=pattern to look for.
  4595                              <1> 	;	DX=Port to test for
  4596                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4597                              <1> 	;	     (normally 30 microseconds per period.)
  4598                              <1> 	;
  4599                              <1> 	;WFP_SHORT:  
  4600                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4601                              <1> 	;
  4602                              <1> 
  4603                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4604                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4605 0000237F B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4606                              <1> ;
  4607                              <1> ;WFPS_OUTER_LP:
  4608                              <1> ;	;
  4609                              <1> ;WFPS_CHECK_PORT:
  4610                              <1> J23:
  4611 00002384 EC                  <1> 	IN	AL,DX			; GET STATUS
  4612 00002385 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4613 00002387 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4614 00002389 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4615                              <1> WFPS_HI:
  4616 0000238B E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4617 0000238D A810                <1> 	TEST	AL,010H			; transition on memory
  4618 0000238F 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4619                              <1> WFPS_LO:
  4620 00002391 E461                <1> 	IN	AL, PORT_B		; SYS1
  4621 00002393 A810                <1> 	TEST	AL,010H
  4622 00002395 74FA                <1> 	JZ	SHORT WFPS_LO
  4623                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4624 00002397 E2EB                <1> 	loop	J23	; 27/02/2015
  4625                              <1> ;	;
  4626                              <1> ;	dec	bl
  4627                              <1> ;	jnz	short WFPS_OUTER_LP
  4628                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4629                              <1> ;J23:
  4630                              <1> ;	IN	AL,DX			; GET STATUS
  4631                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4632                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4633                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4634                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4635                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4636                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4637                              <1>    
  4638                              <1> 	;;27/02/2015
  4639                              <1> 	;16/12/2014
  4640                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4641                              <1> 	;;jb	short J23
  4642                              <1> 
  4643                              <1> ;WFPS_TIMEOUT:
  4644                              <1> 
  4645                              <1> ;-----	FALL THRU TO ERROR RETURN
  4646                              <1> 
  4647 00002399 800D[CC6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4648                              <1> 	;POP	BX			; RESTORE REG.
  4649 000023A0 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4650 000023A1 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4651 000023A2 C3                  <1> 	RETn
  4652                              <1> 
  4653                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4654                              <1> 
  4655                              <1> J27:	
  4656 000023A3 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4657 000023A5 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4658 000023A7 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4659                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4660                              <1> 	; 27/02/2015
  4661 000023A8 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4662                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4663 000023A9 29C9                <1> 	sub	ecx, ecx
  4664 000023AB B103                <1> 	mov	cl, 3 ; 24/12/2021
  4665 000023AD E838F1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4666 000023B2 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4667                              <1> 	;POP	BX			; RESTORE REG
  4668 000023B3 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4669                              <1> 
  4670                              <1> ;-------------------------------------------------------------------------------
  4671                              <1> ; SEEK
  4672                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4673                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4674                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4675                              <1> ;
  4676                              <1> ; ON ENTRY:	DI = DRIVE #
  4677                              <1> ;		CH = TRACK #
  4678                              <1> ;
  4679                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4680                              <1> ;		AX,BX,CX DX DESTROYED
  4681                              <1> ;-------------------------------------------------------------------------------
  4682                              <1> SEEK:
  4683 000023B4 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4684 000023B6 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4685 000023B8 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4686 000023BA D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4687 000023BC 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4688 000023BE 8405[C96B0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4689 000023C4 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4690                              <1> 
  4691 000023C6 0805[C96B0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4692 000023CC E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4693 000023D1 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4694                              <1> 
  4695                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4696                              <1> 
  4697 000023D3 C605[CC6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4698 000023DA E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4699 000023DF 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4700                              <1> 
  4701                              <1> AFT_RECAL:
  4702 000023E1 C687[DD6B0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4703 000023E8 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4704 000023EA 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4705                              <1> 
  4706                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4707                              <1> 
  4708 000023EC F687[D96B0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4709 000023F3 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4710 000023F5 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4711                              <1> 
  4712 000023F7 3AAF[DD6B0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4713 000023FD 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4714                              <1> 
  4715 000023FF BA[32240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4716 00002404 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4717 00002405 88AF[DD6B0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4718 0000240B B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4719 0000240D E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4720 00002412 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4721 00002414 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4722 00002416 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4723 0000241B 8AA7[DD6B0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4724 00002421 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4725 00002426 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4726                              <1> 
  4727                              <1> ;-----	WAIT FOR HEAD SETTLE
  4728                              <1> 
  4729                              <1> DO_WAIT:
  4730 0000242B 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4731 0000242C E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4732 00002431 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4733                              <1> RB:
  4734                              <1> NEC_ERR:
  4735                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4736                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4737 00002432 C3                  <1> 	RETn				; RETURN TO CALLER
  4738                              <1> 
  4739                              <1> ;-------------------------------------------------------------------------------
  4740                              <1> ; RECAL
  4741                              <1> ;	RECALIBRATE DRIVE
  4742                              <1> ;
  4743                              <1> ; ON ENTRY:	DI = DRIVE #
  4744                              <1> ;
  4745                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4746                              <1> ;-------------------------------------------------------------------------------
  4747                              <1> RECAL:
  4748                              <1> 	;PUSH	CX
  4749                              <1> 	; 24/12/2021
  4750 00002433 51                  <1> 	push	ecx
  4751 00002434 B8[50240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4752 00002439 50                  <1> 	PUSH	eAX
  4753 0000243A B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4754 0000243C E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4755 00002441 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4756 00002443 88DC                <1> 	MOV	AH,BL
  4757 00002445 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4758 0000244A E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4759 0000244F 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4760                              <1> RC_BACK:
  4761                              <1> 	;POP	CX
  4762                              <1> 	; 24/12/2021
  4763 00002450 59                  <1> 	pop	ecx
  4764 00002451 C3                  <1> 	RETn
  4765                              <1> 
  4766                              <1> ;-------------------------------------------------------------------------------
  4767                              <1> ; CHK_STAT_2
  4768                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4769                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4770                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4771                              <1> ;
  4772                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4773                              <1> ;-------------------------------------------------------------------------------
  4774                              <1> CHK_STAT_2:
  4775 00002452 B8[7A240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4776 00002457 50                  <1> 	PUSH	eAX
  4777 00002458 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4778 0000245D 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4779 0000245F B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4780 00002461 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4781 00002466 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4782 0000246B 720C                <1> 	JC	short J34
  4783 0000246D A0[CD6B0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4784 00002472 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4785 00002474 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4786 00002476 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4787 00002478 F8                  <1> 	CLC				; GOOD RETURN
  4788                              <1> J34:
  4789 00002479 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4790                              <1> CS_BACK:
  4791 0000247A C3                  <1> 	RETn
  4792                              <1> J35:
  4793 0000247B 800D[CC6B0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4794 00002482 F9                  <1> 	STC				; ERROR RETURN CODE
  4795 00002483 EBF4                <1> 	JMP	SHORT J34
  4796                              <1> 
  4797                              <1> ;-------------------------------------------------------------------------------
  4798                              <1> ; WAIT_INT
  4799                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4800                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4801                              <1> ;	IF THE DRIVE IS NOT READY.
  4802                              <1> ;
  4803                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4804                              <1> ;-------------------------------------------------------------------------------
  4805                              <1> 
  4806                              <1> ; 17/12/2014
  4807                              <1> ; 2.5 seconds waiting !
  4808                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4809                              <1> ; amount of time to wait for completion interrupt from NEC.
  4810                              <1> 
  4811                              <1> 
  4812                              <1> WAIT_INT:
  4813 00002485 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4814 00002486 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4815                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4816                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4817                              <1> 
  4818                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4819                              <1> 	;
  4820                              <1> 	;WAIT_FOR_MEM:	
  4821                              <1> 	;	Waits for a bit at a specified memory location pointed
  4822                              <1> 	;	to by ES:[DI] to become set.
  4823                              <1> 	;INPUT:
  4824                              <1> 	;	AH=Mask to test with.
  4825                              <1> 	;	ES:[DI] = memory location to watch.
  4826                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4827                              <1> 	;	     (normally 30 microseconds per period.)
  4828                              <1> 
  4829                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4830                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4831                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4832                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4833                              <1> 	; 27/02/2015
  4834 00002487 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4835                              <1> WFMS_CHECK_MEM:
  4836 0000248C F605[C96B0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4837 00002493 7516                <1>         jnz     short J37
  4838                              <1> WFMS_HI:
  4839 00002495 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4840 00002497 A810                <1> 	TEST	AL,010H			; transition on memory
  4841 00002499 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4842                              <1> WFMS_LO:
  4843 0000249B E461                <1> 	IN	AL,PORT_B		;SYS1
  4844 0000249D A810                <1> 	TEST	AL,010H
  4845 0000249F 74FA                <1> 	JZ	SHORT WFMS_LO
  4846 000024A1 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4847                              <1> ;WFMS_OUTER_LP:
  4848                              <1> ;;	or	bl, bl			; check outer counter
  4849                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4850                              <1> ;	dec	bl
  4851                              <1> ;	jz	short J36A	
  4852                              <1> ;	jmp	short WFMS_CHECK_MEM
  4853                              <1> 
  4854                              <1> 	;17/12/2014
  4855                              <1> 	;16/12/2014
  4856                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4857                              <1> ;J36:
  4858                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4859                              <1> ;	JNZ	short J37
  4860                              <1> 	;16/12/2014
  4861                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4862                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4863                              <1> 	;JNZ	short J36
  4864                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4865                              <1> ;	jb	short J36
  4866                              <1> 
  4867                              <1> ;WFMS_TIMEOUT:
  4868                              <1> ;J36A:
  4869 000024A3 800D[CC6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4870 000024AA F9                  <1> 	STC				; ERROR RETURN
  4871                              <1> J37:
  4872 000024AB 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4873 000024AC 8025[C96B0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4874 000024B3 9D                  <1> 	POPF				; RECOVER CARRY
  4875 000024B4 C3                  <1> 	RETn				; GOOD RETURN CODE
  4876                              <1> 
  4877                              <1> ;-------------------------------------------------------------------------------
  4878                              <1> ; RESULTS
  4879                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4880                              <1> ;	FOLLOWING AN INTERRUPT.
  4881                              <1> ;
  4882                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4883                              <1> ;		AX,BX,CX,DX DESTROYED
  4884                              <1> ;-------------------------------------------------------------------------------
  4885                              <1> RESULTS:
  4886 000024B5 57                  <1> 	PUSH	eDI
  4887 000024B6 BF[CD6B0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4888 000024BB B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4889 000024BD 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4890                              <1> 
  4891                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4892                              <1> 
  4893                              <1> _R10: 
  4894                              <1> 	; 16/12/2014
  4895                              <1> 	; wait for (max) 0.5 seconds
  4896                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4897                              <1> 	;XOR	CX,CX			; COUNTER
  4898                              <1> 
  4899                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4900                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4901                              <1> 	; 27/02/2015
  4902 000024C1 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4903                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4904                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4905                              <1> 
  4906                              <1> WFPSR_OUTER_LP:
  4907                              <1> 	;
  4908                              <1> WFPSR_CHECK_PORT:
  4909                              <1> J39:					; WAIT FOR MASTER
  4910 000024C6 EC                  <1> 	IN	AL,DX			; GET STATUS
  4911 000024C7 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4912 000024C9 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4913 000024CB 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4914                              <1> WFPSR_HI:
  4915 000024CD E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4916 000024CF A810                <1> 	TEST	AL,010H			; transition on memory
  4917 000024D1 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  4918                              <1> WFPSR_LO:
  4919 000024D3 E461                <1> 	IN	AL, PORT_B		; SYS1
  4920 000024D5 A810                <1> 	TEST	AL,010H
  4921 000024D7 74FA                <1> 	JZ	SHORT WFPSR_LO
  4922 000024D9 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  4923                              <1> 	;; 27/02/2015
  4924                              <1> 	;;dec	bh
  4925                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4926                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4927                              <1> 
  4928                              <1> 	;;mov	byte [wait_count], 0
  4929                              <1> ;J39:					; WAIT FOR MASTER
  4930                              <1> ;	IN	AL,DX			; GET STATUS
  4931                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4932                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4933                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  4934                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  4935                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  4936                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  4937                              <1> 	;
  4938                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  4939                              <1> 	;;jb	short J39	
  4940                              <1> 
  4941                              <1> ;WFPSR_TIMEOUT:
  4942 000024DB 800D[CC6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4943 000024E2 F9                  <1> 	STC				; SET ERROR RETURN
  4944 000024E3 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  4945                              <1> 
  4946                              <1> ;-----	READ IN THE STATUS
  4947                              <1> 
  4948                              <1> J42:
  4949 000024E5 EB00                <1> 	JMP	$+2			; I/O DELAY
  4950 000024E7 6642                <1> 	INC	DX			; POINT AT DATA PORT
  4951 000024E9 EC                  <1> 	IN	AL,DX			; GET THE DATA
  4952                              <1> 	; 16/12/2014
  4953                              <1> 	NEWIODELAY
  2049 000024EA E6EB                <2>  out 0EBh,al
  4954 000024EC 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  4955 000024EE 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  4956                              <1> 	; 16/12/2014
  4957                              <1> ;	push	cx
  4958                              <1> ;	mov	cx, 30
  4959                              <1> ;wdw2:
  4960                              <1> ;	NEWIODELAY
  4961                              <1> ;	loop	wdw2
  4962                              <1> ;	pop	cx
  4963                              <1> 
  4964 000024EF B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4965 000024F4 E8F1EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4966 000024F9 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  4967 000024FB EC                  <1> 	IN	AL,DX			; GET STATUS
  4968                              <1> 	; 16/12/2014
  4969                              <1> 	NEWIODELAY
  2049 000024FC E6EB                <2>  out 0EBh,al
  4970                              <1> 	;
  4971 000024FE A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  4972 00002500 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  4973                              <1> 
  4974 00002502 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  4975 00002504 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  4976 00002506 800D[CC6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  4977 0000250D F9                  <1> 	STC				; SET ERROR FLAG
  4978                              <1> 
  4979                              <1> ;-----	RESULT OPERATION IS DONE
  4980                              <1> POPRES:
  4981 0000250E 5F                  <1> 	POP	eDI
  4982 0000250F C3                  <1> 	RETn				; RETURN WITH CARRY SET
  4983                              <1> 
  4984                              <1> ;-------------------------------------------------------------------------------
  4985                              <1> ; READ_DSKCHNG
  4986                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4987                              <1> ;
  4988                              <1> ; ON ENTRY:	DI = DRIVE #
  4989                              <1> ;
  4990                              <1> ; ON EXIT:	DI = DRIVE #
  4991                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4992                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4993                              <1> ;		AX,CX,DX DESTROYED
  4994                              <1> ;-------------------------------------------------------------------------------
  4995                              <1> READ_DSKCHNG:
  4996 00002510 E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4997 00002515 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  4998 00002519 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  4999 0000251A A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5000 0000251C C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5001                              <1> 
  5002                              <1> ;-------------------------------------------------------------------------------
  5003                              <1> ; DRIVE_DET
  5004                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5005                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5006                              <1> ; ON ENTRY:	DI = DRIVE #
  5007                              <1> ;-------------------------------------------------------------------------------
  5008                              <1> DRIVE_DET:
  5009 0000251D E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5010 00002522 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5011 00002527 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5012 00002529 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5013 0000252B E884FEFFFF          <1> 	CALL	SEEK
  5014 00002530 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5015 00002532 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5016                              <1> SK_GIN:
  5017 00002534 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5018                              <1> 	;PUSH	CX			; SAVE TRACK
  5019                              <1> 	; 24/12/2021
  5020 00002536 51                  <1> 	push	ecx
  5021 00002537 E878FEFFFF          <1> 	CALL	SEEK
  5022 0000253C 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5023 0000253E B8[79250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5024 00002543 50                  <1> 	PUSH	eAX
  5025 00002544 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5026 00002546 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5027 0000254B 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5028 0000254E 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5029 00002550 E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5030 00002555 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5031 0000255A 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5032                              <1> 	;POP	CX			; RESTORE TRACK
  5033                              <1> 	; 24/12/2021
  5034 0000255B 59                  <1> 	pop	ecx
  5035 0000255C F605[CD6B0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5036 00002563 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5037 00002565 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5038 00002567 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5039                              <1> 
  5040                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5041                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5042                              <1> 
  5043 00002569 808F[D96B0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5044 00002570 C3                  <1> 	RETn				; ALL INFORMATION SET
  5045                              <1> IS_80:
  5046 00002571 808F[D96B0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5047                              <1> DD_BAC:
  5048 00002578 C3                  <1> 	RETn
  5049                              <1> POP_BAC:
  5050                              <1> 	;POP	CX			; THROW AWAY
  5051                              <1> 	; 24/12/2021
  5052 00002579 59                  <1> 	pop	ecx
  5053 0000257A C3                  <1> 	RETn
  5054                              <1> 
  5055                              <1> fdc_int:  
  5056                              <1> 	  ; 30/07/2015	
  5057                              <1> 	  ; 16/02/2015
  5058                              <1> ;int_0Eh: ; 11/12/2014
  5059                              <1> 
  5060                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5061                              <1> ; DISK_INT
  5062                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5063                              <1> ;
  5064                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5065                              <1> ;-------------------------------------------------------------------------------
  5066                              <1> DISK_INT_1:
  5067                              <1> 
  5068                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5069                              <1> 	; 24/12/2021
  5070 0000257B 50                  <1> 	push	eax
  5071 0000257C 1E                  <1> 	push	ds
  5072 0000257D 66B81000            <1> 	mov	ax, KDATA
  5073 00002581 8ED8                <1> 	mov 	ds, ax
  5074 00002583 800D[C96B0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5075 0000258A B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5076 0000258C E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5077 0000258E 1F                  <1> 	pop	ds
  5078                              <1> 	;POP	AX			; RECOVER REGISTER
  5079                              <1> 	; 24/12/2021
  5080 0000258F 58                  <1> 	pop	eax
  5081 00002590 CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5082                              <1> 
  5083                              <1> ;-------------------------------------------------------------------------------
  5084                              <1> ; DSKETTE_SETUP
  5085                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5086                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5087                              <1> ;-------------------------------------------------------------------------------
  5088                              <1> DSKETTE_SETUP:
  5089                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5090                              <1> 	;PUSH	BX
  5091                              <1> 	;PUSH	CX
  5092 00002591 52                  <1> 	PUSH	eDX
  5093                              <1> 	;PUSH	DI
  5094                              <1> 	;;PUSH	DS
  5095                              <1> 	; 14/12/2014
  5096                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5097                              <1> 	;mov	[DISK_POINTER+2], cs
  5098                              <1> 	;
  5099                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5100 00002592 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5101 00002594 66C705[D96B0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5101 0000259C 00                  <1>
  5102 0000259D 8025[D46B0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5103 000025A4 800D[D46B0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5104 000025AB C605[C96B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5105 000025B2 C605[CB6B0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5106 000025B9 C605[CA6B0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5107 000025C0 C605[CC6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5108                              <1> 	;
  5109                              <1> 	; 28/02/2015
  5110                              <1> 	;mov	word [cfd], 100h 
  5111 000025C7 E89DF2FFFF          <1> 	call	DSK_RESET
  5112 000025CC 5A                  <1> 	pop	edx
  5113 000025CD C3                  <1> 	retn
  5114                              <1> 
  5115                              <1> ;SUP0:
  5116                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5117                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5118                              <1> ;	; 02/01/2015
  5119                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5120                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5121                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5122                              <1> ;       cmp     byte [fd1_type], 0	
  5123                              <1> ;	jna	short sup1
  5124                              <1> ;	or	di, di
  5125                              <1> ;	jnz	short sup1
  5126                              <1> ;	inc	di
  5127                              <1> ;       jmp     short SUP0
  5128                              <1> ;sup1:
  5129                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5130                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5131                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5132                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5133                              <1> ;	;POP	DI
  5134                              <1> ;	POP	eDX
  5135                              <1> ;	;POP	CX
  5136                              <1> ;	;POP	BX
  5137                              <1> ;	;POP	AX
  5138                              <1> ;	RETn
  5139                              <1> 
  5140                              <1> ;//////////////////////////////////////////////////////
  5141                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5142                              <1> ;
  5143                              <1> 
  5144                              <1> int13h: ; 21/02/2015
  5145 000025CE 9C                  <1> 	pushfd
  5146 000025CF 0E                  <1> 	push 	cs
  5147 000025D0 E858000000          <1> 	call 	DISK_IO
  5148 000025D5 C3                  <1> 	retn
  5149                              <1> 
  5150                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5151                              <1> ;/////////////////////////////////////////////////////////////////////
  5152                              <1> 
  5153                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5154                              <1> ; 23/02/2015
  5155                              <1> ; 21/02/2015 (unix386.s)
  5156                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5157                              <1> ;
  5158                              <1> ; Original Source Code:
  5159                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5160                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5161                              <1> ;
  5162                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5163                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5164                              <1> ;
  5165                              <1> 
  5166                              <1> ;The wait for controller to be not busy is 10 seconds.
  5167                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5168                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5169                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5170                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5171                              <1> 
  5172                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5173                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5174                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5175                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5176                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5177                              <1> 
  5178                              <1> ;The wait for Data request on read and write longs is
  5179                              <1> ;2000 us. (?)
  5180                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5181                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5182                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5183                              <1> 
  5184                              <1> ; Port 61h (PORT_B)
  5185                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5186                              <1> 
  5187                              <1> ; 23/12/2014
  5188                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5189                              <1> 
  5190                              <1> ;--- INT 13H -------------------------------------------------------------------
  5191                              <1> ;									       :
  5192                              <1> ; FIXED DISK I/O INTERFACE						       :
  5193                              <1> ;									       :
  5194                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5195                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5196                              <1> ;									       :
  5197                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5198                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5199                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5200                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5201                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5202                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5203                              <1> ;									       :
  5204                              <1> ;------------------------------------------------------------------------------:
  5205                              <1> ;									       :
  5206                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5207                              <1> ;									       :
  5208                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5209                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5210                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5211                              <1> ;			  DL > 80H - DISK				       :
  5212                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5213                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5214                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5215                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5216                              <1> ;	(AH)= 06H  UNUSED						       :
  5217                              <1> ;	(AH)= 07H  UNUSED						       :
  5218                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5219                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5220                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5221                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5222                              <1> ;	(AH)= 0AH  READ LONG						       :
  5223                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5224                              <1> ;	(AH)= 0CH  SEEK 						       :
  5225                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5226                              <1> ;	(AH)= 0EH  UNUSED						       :
  5227                              <1> ;	(AH)= 0FH  UNUSED						       :
  5228                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5229                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5230                              <1> ;	(AH)= 12H  UNUSED						       :
  5231                              <1> ;	(AH)= 13H  UNUSED						       :
  5232                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5233                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5234                              <1> ;									       :
  5235                              <1> ;-------------------------------------------------------------------------------
  5236                              <1> ;									       :
  5237                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5238                              <1> ;									       :
  5239                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5240                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5241                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5242                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5243                              <1> ;									       :
  5244                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5245                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5246                              <1> ;				 (10 BITS TOTAL)			       :
  5247                              <1> ;									       :
  5248                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5249                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5250                              <1> ;									       :
  5251                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5252                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5253                              <1> ;									       :
  5254                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5255                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5256                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5257                              <1> ;			       80H FOR A BAD SECTOR			       :
  5258                              <1> ;			   N = SECTOR NUMBER				       :
  5259                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5260                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5261                              <1> ;									       :
  5262                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5263                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5264                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5265                              <1> ;									       :
  5266                              <1> ;-------------------------------------------------------------------------------
  5267                              <1> 
  5268                              <1> ;-------------------------------------------------------------------------------
  5269                              <1> ; OUTPUT								       :
  5270                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5271                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5272                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5273                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5274                              <1> ;									       :
  5275                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5276                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5277                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5278                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5279                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5280                              <1> ;		REWRITTEN.						       :
  5281                              <1> ;									       :
  5282                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5283                              <1> ;	   INPUT:							       :
  5284                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5285                              <1> ;	   OUTPUT:							       :
  5286                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5287                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5288                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5289                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5290                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5291                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5292                              <1> ;									       :
  5293                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5294                              <1> ;									       :
  5295                              <1> ;	AH = 0 - NOT PRESENT						       :
  5296                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5297                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5298                              <1> ;	     3 - FIXED DISK						       :
  5299                              <1> ;									       :
  5300                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5301                              <1> ;									       :
  5302                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5303                              <1> ;	INFORMATION.							       :
  5304                              <1> ;									       :
  5305                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5306                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5307                              <1> ;									       :
  5308                              <1> ;-------------------------------------------------------------------------------
  5309                              <1> 
  5310                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5311                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5312                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5313                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5314                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5315                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5316                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5317                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5318                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5319                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5320                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5321                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5322                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5323                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5324                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5325                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5326                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5327                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5328                              <1> 
  5329                              <1> ;--------------------------------------------------------
  5330                              <1> ;							:
  5331                              <1> ; FIXED DISK PARAMETER TABLE				:
  5332                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5333                              <1> ;							:
  5334                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5335                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5336                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5337                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5338                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5339                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5340                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5341                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5342                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5343                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5344                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5345                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5346                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5347                              <1> ;							:
  5348                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5349                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5350                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5351                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5352                              <1> ;							:
  5353                              <1> ;--------------------------------------------------------
  5354                              <1> 
  5355                              <1> ;--------------------------------------------------------
  5356                              <1> ;							:
  5357                              <1> ; HARDWARE SPECIFIC VALUES				:
  5358                              <1> ;							:
  5359                              <1> ;  -  CONTROLLER I/O PORT				:
  5360                              <1> ;							:
  5361                              <1> ;     > WHEN READ FROM: 				:
  5362                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5363                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5364                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5365                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5366                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5367                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5368                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5369                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5370                              <1> ;							:
  5371                              <1> ;     > WHEN WRITTEN TO:				:
  5372                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5373                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5374                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5375                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5376                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5377                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5378                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5379                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5380                              <1> ;							:
  5381                              <1> ;--------------------------------------------------------
  5382                              <1> 
  5383                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5384                              <1> ;HF1_PORT	equ	0170h	
  5385                              <1> ;HF_REG_PORT	EQU	03F6H
  5386                              <1> ;HF1_REG_PORT	equ	0376h
  5387                              <1> 
  5388                              <1> HDC1_BASEPORT	equ	1F0h
  5389                              <1> HDC2_BASEPORT	equ	170h		
  5390                              <1> 
  5391                              <1> align 2
  5392                              <1> 
  5393                              <1> ;-----		STATUS REGISTER
  5394                              <1> 
  5395                              <1> ST_ERROR	EQU	00000001B	;
  5396                              <1> ST_INDEX	EQU	00000010B	;
  5397                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5398                              <1> ST_DRQ		EQU	00001000B	;
  5399                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5400                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5401                              <1> ST_READY	EQU	01000000B	;
  5402                              <1> ST_BUSY 	EQU	10000000B	;
  5403                              <1> 
  5404                              <1> ;-----		ERROR REGISTER
  5405                              <1> 
  5406                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5407                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5408                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5409                              <1> ;		EQU	00001000B	; NOT USED
  5410                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5411                              <1> ;		EQU	00100000B	; NOT USED
  5412                              <1> ERR_DATA_ECC	EQU	01000000B
  5413                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5414                              <1> 
  5415                              <1> 
  5416                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5417                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5418                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5419                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5420                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5421                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5422                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5423                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5424                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5425                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5426                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5427                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5428                              <1> 
  5429                              <1> ;MAX_FILE	EQU	2
  5430                              <1> ;S_MAX_FILE	EQU	2
  5431                              <1> MAX_FILE	equ	4		; 22/12/2014
  5432                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5433                              <1> 
  5434                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5435                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5436                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5437                              <1> 
  5438                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5439                              <1> 
  5440                              <1> ;-----		COMMAND BLOCK REFERENCE
  5441                              <1> 
  5442                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5443                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5444                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5445                              <1> ; 19/12/2014
  5446                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5447                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5448                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5449                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5450                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5451                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5452                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5453                              <1> 
  5454                              <1> align 2
  5455                              <1> 
  5456                              <1> ;----------------------------------------------------------------
  5457                              <1> ; FIXED DISK I/O SETUP						:
  5458                              <1> ;								:
  5459                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5460                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5461                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5462                              <1> ;								:
  5463                              <1> ;----------------------------------------------------------------
  5464                              <1> 
  5465                              <1> DISK_SETUP:
  5466                              <1> 	;CLI
  5467                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5468                              <1> 	;xor	ax,ax
  5469                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5470                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5471                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5472                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5473                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5474                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5475                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5476                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5477                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5478                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5479                              <1> 	;;MOV	[HDISK_INT+2],CS
  5480                              <1> 	;mov	[HDISK_INT1+2],CS
  5481                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5482                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5483                              <1> 	;mov	[HDISK_INT2+2],CS
  5484                              <1> 	;
  5485                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5486                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5487                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5488                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5489                              <1> 	;push	cs
  5490                              <1> 	;pop	ds
  5491                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5492                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5493 000025D6 C705[E46B0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5493 000025DE 0900                <1>
  5494                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5495                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5496 000025E0 C705[E86B0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5496 000025E8 0900                <1>
  5497                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5498                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5499 000025EA C705[EC6B0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5499 000025F2 0900                <1>
  5500                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5501                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5502 000025F4 C705[F06B0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5502 000025FC 0900                <1>
  5503                              <1> 	;
  5504                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5505                              <1> 	;;;AND	AL,0BFH
  5506                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5507                              <1> 	;;;JMP	$+2
  5508                              <1> 	;;IODELAY
  5509                              <1> 	;;OUT	INTB01,AL
  5510                              <1> 	;;IODELAY
  5511                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5512                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5513                              <1> 	;;;JMP	$+2
  5514                              <1> 	;;IODELAY
  5515                              <1> 	;;OUT	INTA01,AL
  5516                              <1> 	;
  5517                              <1> 	;STI
  5518                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5519                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5520                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5521                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5522                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5523                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5524                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5525                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5526                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5527                              <1> 	;mov	si, hd0_type
  5528 000025FE BE[40660000]        <1> 	mov	esi, hd0_type
  5529                              <1> 	;mov	cx, 4
  5530 00002603 B904000000          <1> 	mov	ecx, 4
  5531                              <1> hde_l:
  5532 00002608 AC                  <1> 	lodsb
  5533 00002609 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5534 0000260B 7206                <1> 	jb	short _L4
  5535 0000260D FE05[E06B0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5536                              <1> _L4: ; 26/02/2015
  5537 00002613 E2F3                <1> 	loop	hde_l	
  5538                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5539                              <1> ;L4:
  5540                              <1> 	; 
  5541                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5542                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5543                              <1> 	;;mov 	cl, 3
  5544                              <1> 	;;
  5545                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5546                              <1> ;;hdc_dl:
  5547                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5548                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5549                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5550                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5551                              <1> 	;;jnc	short hdc_reset0
  5552                              <1> 	;;loop	hdc_dl
  5553                              <1> 	;;; 27/12/2014
  5554                              <1> 	;;stc
  5555                              <1> 	;;retn
  5556                              <1> 	;
  5557                              <1> ;;hdc_reset0:
  5558                              <1> 	; 18/01/2015
  5559 00002615 8A0D[E06B0000]      <1> 	mov	cl, [HF_NUM]
  5560 0000261B 20C9                <1> 	and	cl, cl
  5561 0000261D 740D                <1> 	jz	short POD_DONE
  5562                              <1> 	;
  5563 0000261F B27F                <1> 	mov	dl, 7Fh
  5564                              <1> hdc_reset1:
  5565 00002621 FEC2                <1> 	inc	dl
  5566                              <1> 	;; 31/12/2015
  5567                              <1> 	;;push	dx
  5568                              <1> 	;;push	cx
  5569                              <1> 	;;push	ds
  5570                              <1> 	;;sub	ax, ax
  5571                              <1> 	;;mov	ds, ax
  5572                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5573                              <1> 	;;pop	ds
  5574                              <1> 	;;MOV	BX,AX
  5575                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5576                              <1> 	;;MOV	CX,AX
  5577                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5578                              <1> 	;;
  5579                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5580                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5581                              <1> 	;;pop	cx
  5582                              <1> 	;;pop	dx
  5583                              <1> 	;;
  5584                              <1> 	; 18/01/2015
  5585 00002623 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5586                              <1> 	;int	13h
  5587 00002625 E8A4FFFFFF          <1> 	call	int13h
  5588 0000262A E2F5                <1> 	loop	hdc_reset1
  5589                              <1> POD_DONE:
  5590 0000262C C3                  <1> 	RETn
  5591                              <1> 
  5592                              <1> ;;-----	POD_ERROR
  5593                              <1> 
  5594                              <1> ;;CTL_ERRX:
  5595                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5596                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5597                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5598                              <1> ;	;JMP	short POD_DONE
  5599                              <1> 
  5600                              <1> ;;HD_RESET_1:
  5601                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5602                              <1> ;;	;PUSH	CX
  5603                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5604                              <1> ;;	INT	13H
  5605                              <1> ;;	JC	short RES_2
  5606                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5607                              <1> ;;	INT	13H
  5608                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5609                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5610                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5611                              <1> ;;					; (30 seconds)		
  5612                              <1> ;;	;cmc
  5613                              <1> ;;	;JNC	short RES_1
  5614                              <1> ;;	jb	short RES_1
  5615                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5616                              <1> ;;	;TEST	DL,1
  5617                              <1> ;;	;JNZ	RES_E1
  5618                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5619                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5620                              <1> ;;	;JMP	SHORT RES_E1
  5621                              <1> ;;RES_ER: ; 22/12/2014
  5622                              <1> ;;RES_OK:
  5623                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5624                              <1> ;;	;POP	BX
  5625                              <1> ;;	RETn
  5626                              <1> ;;
  5627                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5628                              <1> ;;	INT	13H
  5629                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5630                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5631                              <1> ;;	INT	13H
  5632                              <1> ;;	JC	short RES_ER
  5633                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5634                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5635                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5636                              <1> ;;	INT	13H
  5637                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5638                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5639                              <1> ;;	JE	short RES_OK
  5640                              <1> ;;	CMP	AH,DATA_CORRECTED
  5641                              <1> ;;	JE	short RES_OK
  5642                              <1> ;;	CMP	AH,BAD_ECC
  5643                              <1> ;;	JE	short RES_OK
  5644                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5645                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5646                              <1> ;;					; (60 seconds)		
  5647                              <1> ;;	cmc
  5648                              <1> ;;	JC	short RES_ER		; FAILED
  5649                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5650                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5651                              <1> ;;	AND	AL,3FH
  5652                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5653                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5654                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5655                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5656                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5657                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5658                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5659                              <1> ;;	;TEST	DL,1
  5660                              <1> ;;	;JNZ	short RES_E1
  5661                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5662                              <1> ;;;RES_E1:
  5663                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5664                              <1> ;;;RES_OK:
  5665                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5666                              <1> ;;	;POP	BX
  5667                              <1> ;;	;RETn
  5668                              <1> ;
  5669                              <1> ;;SET_FAIL:
  5670                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5671                              <1> ;	;CALL	CMOS_READ
  5672                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5673                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5674                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5675                              <1> ;	;RETn
  5676                              <1> ;
  5677                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5678                              <1> ;	;POP	AX			; SAVE RETURN
  5679                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5680                              <1> ;	;POP	BX
  5681                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5682                              <1> ;	;PUSH	CX
  5683                              <1> ;	;PUSH	AX
  5684                              <1> ;	;push	ds
  5685                              <1> ;	;xor	ax, ax
  5686                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5687                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5688                              <1> ;	;				; BX = START TIME
  5689                              <1> ;	;				; CX = END TIME
  5690                              <1> ;	;pop	ds
  5691                              <1> ;	;CMP	BX,CX
  5692                              <1> ;	;JB	short TCHK1		; START < END
  5693                              <1> ;	;CMP	BX,AX
  5694                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5695                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5696                              <1> ;;TCHK1: CMP	AX,BX
  5697                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5698                              <1> ;;TCHK2: CMP	AX,CX
  5699                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5700                              <1> ;;					; OR CURRENT < END < START
  5701                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5702                              <1> ;;	RETn
  5703                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5704                              <1> ;;	RETn
  5705                              <1> ;;
  5706                              <1> ;;int_13h:
  5707                              <1> 
  5708                              <1> ;----------------------------------------
  5709                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5710                              <1> ;----------------------------------------
  5711                              <1> 
  5712                              <1> DISK_IO:
  5713 0000262D 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5714                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5715                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5716                              <1> 	;;call	int40h
  5717                              <1> 	;jb	DISKETTE_IO_1
  5718                              <1> 	; 24/12/2021
  5719 00002630 7305                <1> 	jnb	short A1
  5720 00002632 E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5721                              <1> ;RET_2:
  5722                              <1> 	;RETf	2			; BACK TO CALLER
  5723                              <1> ;	retf	4
  5724                              <1> A1:
  5725 00002637 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5726                              <1> 	;; 04/01/2015
  5727                              <1> 	;;OR	AH,AH
  5728                              <1> 	;;JNZ	short A2
  5729                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5730                              <1> 	;;SUB	AH,AH
  5731 00002638 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5732 0000263B 772E                <1> 	JA	short RET_2
  5733                              <1> 	; 18/01/2015
  5734 0000263D 08E4                <1> 	or	ah,ah
  5735 0000263F 742D                <1> 	jz	short A4
  5736 00002641 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5737 00002644 7504                <1> 	jne	short A2
  5738 00002646 28E4                <1> 	sub	ah,ah	; Reset
  5739 00002648 EB24                <1> 	jmp	short A4
  5740                              <1> A2:
  5741 0000264A 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5742                              <1> 	;JNZ	short A3
  5743                              <1>         ;JMP    GET_PARM_N
  5744                              <1> 	;je	GET_PARM_N
  5745                              <1> 	; 24/12/2021
  5746 0000264D 7505                <1> 	jne	short A3
  5747 0000264F E90D030000          <1> 	jmp	GET_PARM_N
  5748                              <1> A3:	
  5749 00002654 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5750                              <1> 	;JNZ	short A4
  5751                              <1>         ;JMP    READ_DASD_TYPE
  5752                              <1> 	;je	READ_DASD_TYPE
  5753                              <1> 	; 24/12/2021
  5754 00002657 7505                <1> 	jne	short A3_A4
  5755 00002659 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5756                              <1> A3_A4:
  5757                              <1> 	; 02/02/2015
  5758 0000265E 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5759                              <1> 	; 12/01/2015
  5760 00002661 F5                  <1> 	cmc
  5761 00002662 730A                <1> 	jnc	short A4
  5762                              <1> 	; 30/01/2015
  5763                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5764 00002664 C605[DF6B0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5765                              <1> 	;jmp	short RET_2
  5766                              <1> RET_2:
  5767 0000266B CA0400              <1> 	retf	4
  5768                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5769 0000266E C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5770 00002672 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5771 00002673 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5772 00002674 52                  <1> 	PUSH	eDX
  5773 00002675 1E                  <1> 	PUSH	DS
  5774 00002676 06                  <1> 	PUSH	ES
  5775 00002677 56                  <1> 	PUSH	eSI
  5776 00002678 57                  <1> 	PUSH	eDI
  5777                              <1> 	;;04/01/2015
  5778                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5779                              <1> 	;;JNZ	short A5
  5780                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5781                              <1> ;;A5:	
  5782                              <1> 	;push	cs
  5783                              <1> 	;pop	ds
  5784                              <1> 	; 21/02/2015
  5785                              <1> 	;push	ax
  5786                              <1> 	; 24/12/2021
  5787 00002679 50                  <1> 	push	eax
  5788 0000267A 66B81000            <1> 	mov	ax, KDATA
  5789 0000267E 8ED8                <1> 	mov	ds, ax
  5790 00002680 8EC0                <1> 	mov	es, ax	
  5791                              <1> 	;pop	ax
  5792                              <1> 	; 24/12/2021
  5793 00002682 58                  <1> 	pop	eax
  5794 00002683 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5795                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5796 00002688 8A25[DF6B0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5797 0000268E 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5798 00002691 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5799 00002692 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5800 00002693 5E                  <1> 	POP	eSI
  5801 00002694 07                  <1>         POP     ES
  5802 00002695 1F                  <1>         POP     DS
  5803 00002696 5A                  <1> 	POP	eDX
  5804 00002697 59                  <1> 	POP	eCX
  5805 00002698 5B                  <1> 	POP	eBX
  5806 00002699 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5807                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5808 0000269A CA0400              <1> 	retf	4
  5809                              <1> ; 21/02/2015
  5810                              <1> ;       dw --> dd
  5811                              <1> M1:					; FUNCTION TRANSFER TABLE
  5812 0000269D [56280000]          <1> 	dd	DISK_RESET		; 000H
  5813 000026A1 [CB280000]          <1> 	dd	RETURN_STATUS		; 001H
  5814 000026A5 [D8280000]          <1> 	dd	DISK_READ		; 002H
  5815 000026A9 [E1280000]          <1> 	dd	DISK_WRITE		; 003H
  5816 000026AD [EA280000]          <1> 	dd	DISK_VERF		; 004H
  5817 000026B1 [02290000]          <1> 	dd	FMT_TRK 		; 005H
  5818 000026B5 [4C280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5819 000026B9 [4C280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5820 000026BD [4C280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5821 000026C1 [C3290000]          <1> 	dd	INIT_DRV		; 009H
  5822 000026C5 [222A0000]          <1> 	dd	RD_LONG 		; 00AH
  5823 000026C9 [2B2A0000]          <1> 	dd	WR_LONG 		; 00BH
  5824 000026CD [342A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5825 000026D1 [56280000]          <1> 	dd	DISK_RESET		; 00DH
  5826 000026D5 [4C280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5827 000026D9 [4C280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5828 000026DD [5C2A0000]          <1> 	dd	TST_RDY 		; 010H
  5829 000026E1 [802A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5830 000026E5 [4C280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5831 000026E9 [4C280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5832 000026ED [B62A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5833                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5834 000026F1 [4C280000]          <1> 	dd	BAD_COMMAND		; 015h
  5835 000026F5 [4C280000]          <1> 	dd	BAD_COMMAND		; 016h
  5836 000026F9 [4C280000]          <1> 	dd	BAD_COMMAND		; 017h
  5837 000026FD [4C280000]          <1> 	dd	BAD_COMMAND		; 018h
  5838 00002701 [4C280000]          <1> 	dd	BAD_COMMAND		; 019h
  5839 00002705 [4C280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5840 00002709 [D8280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5841 0000270D [E1280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5842                              <1> M1L     EQU    $-M1
  5843                              <1> 
  5844                              <1> DISK_IO_CONT:
  5845                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5846 00002711 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5847                              <1> 	;;JNZ	short SU0
  5848                              <1>         ;;JMP	RETURN_STATUS
  5849                              <1> 	;je	RETURN_STATUS
  5850                              <1> 	; 24/12/2021
  5851 00002714 7505                <1> 	jne	short SU0
  5852 00002716 E9B0010000          <1> 	jmp	RETURN_STATUS
  5853                              <1> SU0:
  5854 0000271B C605[DF6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5855                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5856                              <1> 	;mov	si, bx ;; 14/02/2015
  5857 00002722 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5858 00002724 8A1D[E06B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5859                              <1> 	;; 04/01/2015
  5860                              <1> 	;;PUSH	AX
  5861 0000272A 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5862                              <1> 					; (get drive number as 0 to 3)
  5863 0000272D 38D3                <1> 	CMP	BL,DL
  5864                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5865                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5866                              <1> 	; 24/12/2021
  5867 0000272F 7705                <1> 	ja	short su0_su1
  5868 00002731 E916010000          <1> 	jmp	BAD_COMMAND
  5869                              <1> su0_su1:
  5870                              <1>         ;;03/01/2015
  5871 00002736 29DB                <1> 	sub	ebx, ebx
  5872 00002738 88D3                <1> 	mov	bl, dl
  5873                              <1> 	;sub	bh, bh
  5874 0000273A 883D[F46B0000]      <1> 	mov	[LBAMode], bh 	; 0
  5875                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5876                              <1> 	;test	byte [ebx+hd0_type], 1
  5877                              <1> 	;jz	short su1		; no
  5878                              <1> 	;inc	byte [LBAMode]
  5879                              <1> ;su1:
  5880                              <1> 	; 21/02/2015 (32 bit modification)
  5881                              <1> 	; 04/01/2015
  5882                              <1> 	;push	ax ; ***
  5883                              <1> 	; 24/12/2021
  5884 00002740 50                  <1> 	push	eax ; ***
  5885                              <1> 	;PUSH	ES ; **
  5886                              <1> 	;PUSH	DX ; *
  5887                              <1> 	; 24/12/2021
  5888 00002741 52                  <1> 	push	edx ; *
  5889                              <1> 	;push	ax
  5890 00002742 50                  <1> 	push	eax
  5891 00002743 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5892                              <1> 	; 02/02/2015
  5893                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5894 00002748 668B4310            <1> 	mov	ax, [ebx+16]
  5895 0000274C 66A3[34660000]      <1> 	mov	[HF_PORT], ax
  5896                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5897 00002752 668B5312            <1> 	mov	dx, [ebx+18]
  5898 00002756 668915[36660000]    <1> 	mov	[HF_REG_PORT], dx
  5899                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5900 0000275D 8A4314              <1> 	mov	al, [ebx+20]
  5901                              <1> 	; 23/02/2015
  5902 00002760 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5903 00002762 7406                <1> 	jz 	short su1
  5904 00002764 FE05[F46B0000]      <1> 	inc	byte [LBAMode] ; 1 
  5905                              <1> su1: 	 
  5906 0000276A C0E804              <1> 	shr 	al, 4
  5907 0000276D 2401                <1> 	and	al, 1			
  5908 0000276F A2[38660000]        <1> 	mov	[hf_m_s], al 
  5909                              <1> 	;
  5910                              <1> 	; 03/01/2015
  5911                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5912 00002774 8A4308              <1> 	mov	al, [ebx+8]
  5913                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5914 00002777 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  5915                              <1> 					; Control Byte:  (= 08h, here)
  5916                              <1> 					; bit 0 - 0
  5917                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5918                              <1> 					; bit 2 - SRST (software RESET)
  5919                              <1> 					; bit 3 - use extra heads (8 to 15)
  5920                              <1> 					;         -always set to 1-	
  5921                              <1> 					; (bits 3 to 7 are reserved
  5922                              <1> 					;          for ATA devices)
  5923 00002778 8A25[E16B0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5924 0000277E 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  5925 00002781 08C4                <1> 	OR	AH,AL
  5926 00002783 8825[E16B0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  5927                              <1> 	; 04/01/2015
  5928                              <1> 	;pop	ax
  5929                              <1> 	; 24/12/2021
  5930 00002789 58                  <1> 	pop	eax
  5931                              <1> 	;pop	dx ; * ;; 14/02/2015
  5932                              <1> 	; 24/12/2021
  5933 0000278A 5A                  <1> 	pop	edx ; *
  5934 0000278B 20E4                <1> 	and	ah, ah	; Reset function ?
  5935 0000278D 7506                <1> 	jnz	short su2
  5936                              <1> 	;;pop	dx ; * ;; 14/02/2015
  5937                              <1> 	;pop	es ; **
  5938                              <1> 	;pop	ax ; ***
  5939                              <1> 	; 24/12/2021
  5940 0000278F 58                  <1> 	pop	eax ; ***	
  5941                              <1> 	;;pop	bx
  5942 00002790 E9C1000000          <1>         jmp     DISK_RESET
  5943                              <1> su2:
  5944 00002795 803D[F46B0000]00    <1> 	cmp	byte [LBAMode], 0
  5945 0000279C 765E                <1> 	jna	short su3
  5946                              <1> 	;
  5947                              <1> 	; 02/02/2015 (LBA read/write function calls)
  5948 0000279E 80FC1B              <1> 	cmp	ah, 1Bh
  5949 000027A1 720B                <1> 	jb	short lbarw1
  5950 000027A3 80FC1C              <1> 	cmp	ah, 1Ch
  5951 000027A6 7759                <1> 	ja 	short invldfnc
  5952                              <1> 	;;pop	dx ; * ; 14/02/2015
  5953                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5954 000027A8 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5955                              <1> 	;; 14/02/2015
  5956 000027AA 88D1                <1> 	mov	cl, dl ; 14/02/2015
  5957                              <1> 	;;mov	dx, bx
  5958                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5959                              <1> 	;;mov	bx, di
  5960                              <1> 	;mov	si, di ; Buffer offset
  5961 000027AC EB2E                <1> 	jmp	short lbarw2
  5962                              <1> lbarw1:
  5963                              <1> 	; convert CHS to LBA
  5964                              <1> 	;
  5965                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5966                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5967                              <1> 	;	+ Sector - 1
  5968                              <1> 	;push	dx ; * ;; 14/02/2015
  5969                              <1> 	; 24/12/2021
  5970 000027AE 52                  <1> 	push	edx ; *
  5971                              <1> 	;xor	dh, dh
  5972 000027AF 31D2                <1> 	xor	edx, edx
  5973                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  5974 000027B1 8A530E              <1> 	mov	dl, [ebx+14]
  5975                              <1> 	;xor	ah, ah
  5976 000027B4 31C0                <1> 	xor	eax, eax
  5977                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  5978 000027B6 8A4302              <1> 	mov	al, [ebx+2]
  5979 000027B9 FEC8                <1> 	dec	al
  5980                              <1> 	;inc	ax		; 0 =  256
  5981 000027BB 40                  <1> 	inc	eax ; 24/12/2021
  5982 000027BC 66F7E2              <1> 	mul 	dx
  5983                              <1> 		; AX = # of Heads" * Sectors/Track
  5984 000027BF 6689CA              <1> 	mov	dx, cx
  5985                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  5986 000027C2 83E13F              <1> 	and	ecx, 3fh
  5987 000027C5 86D6                <1> 	xchg	dl, dh
  5988 000027C7 C0EE06              <1> 	shr	dh, 6
  5989                              <1> 		; DX = cylinder (0 to 1023)
  5990                              <1> 	;mul 	dx
  5991                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  5992 000027CA F7E2                <1> 	mul	edx
  5993 000027CC FEC9                <1> 	dec	cl  ; sector - 1
  5994                              <1> 	;add	ax, cx
  5995                              <1> 	;adc	dx, 0
  5996                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  5997 000027CE 01C8                <1> 	add	eax, ecx
  5998                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5999                              <1> 	; 24/12/2021
  6000 000027D0 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6001                              <1> 	;push	dx
  6002                              <1> 	;push	ax
  6003 000027D1 50                  <1> 	push	eax
  6004                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6005 000027D2 8A430E              <1> 	mov	al, [ebx+14]
  6006 000027D5 F6E5                <1> 	mul	ch
  6007                              <1> 		; AX = Head * Sectors/Track
  6008 000027D7 6699                <1>         cwd
  6009                              <1> 	;pop	dx
  6010 000027D9 5A                  <1> 	pop	edx
  6011                              <1> 	;add	ax, dx
  6012                              <1> 	;pop	dx
  6013                              <1> 	;adc	dx, 0 ; add carry bit
  6014 000027DA 01D0                <1> 	add	eax, edx
  6015                              <1> lbarw2:
  6016 000027DC 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6017 000027DE 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6018 000027E0 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6019                              <1> 				; NOTE: Features register (1F1h, 171h)
  6020                              <1> 				; is not used for ATA device R/W functions. 
  6021                              <1> 				; It is old/obsolete 'write precompensation'
  6022                              <1> 				; register and error register
  6023                              <1> 				; for old ATA/IDE devices.
  6024                              <1> 	; 18/01/2014
  6025                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6026 000027E4 8A0D[38660000]      <1> 	mov	cl, [hf_m_s]
  6027                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6028                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6029                              <1> 				; bit 6 = 1 = LBA mode
  6030                              <1> 				; bit 7 = 1
  6031 000027EA 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6032                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6033 000027ED 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6034 000027F2 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6035                              <1> 	;or	dh, ch
  6036 000027F5 09C8                <1> 	or	eax, ecx	
  6037                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6038                              <1> 				  ; (Sector Number Register)
  6039                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6040                              <1> 				  ; (Cylinder Low Register)
  6041                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6042                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6043                              <1> 				  ; (Cylinder High Register)
  6044                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6045                              <1> 				  ; (Drive/Head Register)
  6046                              <1> 	
  6047                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6048 000027F7 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6049                              <1> 	;14/02/2015
  6050                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6051 000027FA EB37                <1> 	jmp	short su4
  6052                              <1> su3:
  6053                              <1> 	; 02/02/2015 
  6054                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6055 000027FC 80FC14              <1> 	cmp 	ah, 14h
  6056 000027FF 7603                <1> 	jna 	short chsfnc
  6057                              <1> invldfnc:
  6058                              <1>         ; 14/02/2015  
  6059                              <1> 	;pop	es ; **
  6060                              <1>         ;pop	ax ; ***
  6061                              <1>         ; 24/12/2021
  6062 00002801 58                  <1> 	pop	eax ; ***
  6063                              <1> 	;jmp	short BAD_COMMAND_POP
  6064 00002802 EB48                <1>         jmp     short BAD_COMMAND
  6065                              <1> chsfnc:	
  6066                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6067 00002804 668B4305            <1> 	mov	ax, [ebx+5]
  6068 00002808 66C1E802            <1> 	SHR	AX,2
  6069 0000280C 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6070                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6071                              <1> 	;;PUSH	DX
  6072                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6073                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6074                              <1> 	;;POP	DX ; * 
  6075                              <1> 	;;POP	ES ; **
  6076                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6077                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6078                              <1> 	;;OR	AH,AL
  6079                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6080                              <1> 	;
  6081 0000280F 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6082 00002811 243F                <1> 	AND	AL,3FH
  6083 00002813 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6084 00002816 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6085 00002819 88C8                <1> 	MOV	AL,CL
  6086 0000281B C0E806              <1> 	SHR	AL,6
  6087 0000281E 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6088                              <1> 	;;05/01/2015
  6089                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6090 00002821 A0[38660000]        <1> 	mov	al, [hf_m_s]
  6091 00002826 C0E004              <1> 	SHL	AL,4
  6092 00002829 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6093 0000282C 08F0                <1> 	OR	AL,DH
  6094                              <1> 	;OR	AL,80H or 20H
  6095 0000282E 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6096 00002830 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6097                              <1> su4:
  6098                              <1> 	;POP	ES ; **
  6099                              <1>         ;; 14/02/2015
  6100                              <1>         ;;POP   AX
  6101                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6102                              <1>         ;;PUSH  AX
  6103                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6104                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6105                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6106                              <1> 	;pop     ax ; ***
  6107                              <1> 	; 24/12/2021
  6108 00002833 58                  <1> 	pop	eax ; ***
  6109 00002834 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6110 00002837 29DB                <1>         sub	ebx, ebx
  6111 00002839 88E3                <1> 	mov     bl, ah
  6112                              <1>         ;xor	bh, bh
  6113                              <1>         ;sal	bx, 1
  6114 0000283B 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6115                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6116                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6117                              <1>         ;;JNB   short BAD_COMMAND_POP
  6118                              <1>         ;cmp	bx, M1L
  6119 0000283F 83FB74              <1> 	cmp	ebx, M1L
  6120 00002842 7308                <1> 	jnb	short BAD_COMMAND
  6121                              <1>         ;xchg	bx, si
  6122 00002844 87DE                <1>         xchg	ebx, esi
  6123                              <1> 	;;;POP	AX			; RESTORE AX
  6124                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6125                              <1> 	
  6126                              <1> 	;;PUSH	CX
  6127                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6128                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6129                              <1> 	;SHR	CX,4
  6130                              <1> 	;MOV	AX,ES
  6131                              <1> 	;ADD	AX,CX
  6132                              <1> 	;MOV	ES,AX
  6133                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6134                              <1> 	;;POP	AX
  6135                              <1> 	;;POP	CX
  6136                              <1> 	;;JMP	word [CS:SI+M1]
  6137                              <1> 	;jmp	word [SI+M1]
  6138 00002846 FFA6[9D260000]      <1> 	jmp	dword [esi+M1]
  6139                              <1> ;;BAD_COMMAND_POP:
  6140                              <1> ;;	POP	AX
  6141                              <1> ;;	POP	BX
  6142                              <1> BAD_COMMAND:
  6143 0000284C C605[DF6B0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6144 00002853 B000                <1> 	MOV	AL,0
  6145 00002855 C3                  <1> 	RETn
  6146                              <1> 
  6147                              <1> ;----------------------------------------
  6148                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6149                              <1> ;----------------------------------------
  6150                              <1> 
  6151                              <1> ; 18-1-2015 : one controller reset (not other one)
  6152                              <1> 
  6153                              <1> DISK_RESET:
  6154 00002856 FA                  <1> 	CLI
  6155 00002857 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6156                              <1> 	;JMP	$+2
  6157                              <1> 	IODELAY
  2044 00002859 EB00                <2>  jmp short $+2
  2045 0000285B EB00                <2>  jmp short $+2
  6158                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6159 0000285D 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6160 0000285F E6A1                <1> 	OUT	INTB01,AL
  6161 00002861 FB                  <1> 	STI				; START INTERRUPTS
  6162                              <1> 	; 14/02/2015
  6163                              <1> 	;mov	di, dx
  6164                              <1> 	; 24/12/2021
  6165 00002862 89D7                <1> 	mov	edi, edx	
  6166                              <1> 	; 04/01/2015
  6167                              <1> 	;xor	di,di
  6168                              <1> drst0:
  6169 00002864 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6170                              <1> 	;MOV	DX,HF_REG_PORT
  6171 00002866 668B15[36660000]    <1> 	MOV	DX,[HF_REG_PORT]
  6172 0000286D EE                  <1> 	OUT	DX,AL			; RESET
  6173                              <1> ;	MOV	CX,10			; DELAY COUNT
  6174                              <1> ;DRD:	DEC	CX
  6175                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6176                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6177 0000286E B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6178 00002873 E872ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6179                              <1>                                         ; 40 micro seconds)
  6180 00002878 A0[E16B0000]        <1> 	mov	al,[CONTROL_BYTE]
  6181 0000287D 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6182 0000287F EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6183 00002880 E807040000          <1> 	CALL	NOT_BUSY
  6184 00002885 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6185 00002887 668B15[34660000]    <1> 	MOV	DX,[HF_PORT]
  6186 0000288E FEC2                <1> 	inc	dl  ; HF_PORT+1
  6187                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6188                              <1>         ;mov	cl, 10
  6189 00002890 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6190                              <1> drst1:
  6191 00002895 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6192 00002896 3C01                <1> 	CMP	AL,1
  6193                              <1> 	; 04/01/2015
  6194 00002898 740A                <1> 	jz	short drst2
  6195                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6196                              <1>         	; Drive/Head Register - bit 4
  6197 0000289A E2F9                <1> 	loop	drst1
  6198                              <1> DRERR:	
  6199 0000289C C605[DF6B0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6200 000028A3 C3                  <1> 	RETn
  6201                              <1> drst2:
  6202                              <1> 	; 14/02/2015
  6203                              <1> 	;mov	dx, di
  6204                              <1> 	; 24/12/2021
  6205 000028A4 89FA                <1> 	mov	edx, edi
  6206                              <1> ;drst3:
  6207                              <1> ;	; 05/01/2015
  6208                              <1> ;	shl 	di,1
  6209                              <1> ;	; 04/01/2015
  6210                              <1> ;	mov	ax,[di+hd_cports]
  6211                              <1> ;	cmp	ax,[HF_REG_PORT]
  6212                              <1> ;	je	short drst4
  6213                              <1> ;	mov	[HF_REG_PORT], ax
  6214                              <1> ;	; 03/01/2015
  6215                              <1> ;	mov	ax,[di+hd_ports]
  6216                              <1> ;       mov     [HF_PORT], ax
  6217                              <1> ;	; 05/01/2014
  6218                              <1> ;	shr	di,1
  6219                              <1> ;	; 04/01/2015
  6220                              <1> ;	jmp	short drst0	; reset other controller
  6221                              <1> ;drst4:
  6222                              <1> ;	; 05/01/2015
  6223                              <1> ;	shr	di,1
  6224                              <1> ;	mov	al,[di+hd_dregs]
  6225                              <1> ;	and	al,10h ; bit 4 only
  6226                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6227                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6228                              <1> 	;
  6229 000028A6 A0[38660000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6230 000028AB A801                <1> 	test	al,1
  6231                              <1> ;	jnz	short drst6
  6232 000028AD 7516                <1>         jnz     short drst4
  6233 000028AF 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6234                              <1> ;drst5:
  6235                              <1> drst3:
  6236 000028B3 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6237                              <1> 	;mov	dx,di
  6238 000028B8 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6239                              <1> 	; 04/01/2014
  6240                              <1> ;	inc	di
  6241                              <1> ;	mov	dx,di
  6242                              <1> ;	cmp	dl,[HF_NUM]
  6243                              <1> ;	jb	short drst3
  6244                              <1> ;DRE:
  6245 000028BD C605[DF6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6246 000028C4 C3                  <1> 	RETn
  6247                              <1> ;drst6:
  6248                              <1> drst4:		; Drive/Head Register - bit 4
  6249 000028C5 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6250                              <1>         ;jmp    short drst5
  6251 000028C9 EBE8                <1>         jmp     short drst3
  6252                              <1> 
  6253                              <1> ;----------------------------------------
  6254                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6255                              <1> ;----------------------------------------
  6256                              <1> 
  6257                              <1> RETURN_STATUS:
  6258 000028CB A0[DF6B0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6259 000028D0 C605[DF6B0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6260 000028D7 C3                  <1> 	RETn
  6261                              <1> 
  6262                              <1> ;----------------------------------------
  6263                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6264                              <1> ;----------------------------------------
  6265                              <1> 
  6266                              <1> DISK_READ:
  6267 000028D8 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6268 000028DC E92A020000          <1>         JMP     COMMANDI
  6269                              <1> 
  6270                              <1> ;----------------------------------------
  6271                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6272                              <1> ;----------------------------------------
  6273                              <1> 
  6274                              <1> DISK_WRITE:
  6275 000028E1 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6276 000028E5 E976020000          <1>         JMP     COMMANDO
  6277                              <1> 
  6278                              <1> ;----------------------------------------
  6279                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6280                              <1> ;----------------------------------------
  6281                              <1> 
  6282                              <1> DISK_VERF:
  6283 000028EA C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6284 000028EE E8E4020000          <1> 	CALL	COMMAND
  6285 000028F3 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6286 000028F5 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6287 000028FA 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6288 000028FC E8E3030000          <1> 	CALL	CHECK_STATUS
  6289                              <1> VERF_EXIT:
  6290 00002901 C3                  <1> 	RETn
  6291                              <1> 
  6292                              <1> ;----------------------------------------
  6293                              <1> ;	FORMATTING	     (AH = 05H) :
  6294                              <1> ;----------------------------------------
  6295                              <1> 
  6296                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6297 00002902 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6298                              <1> 	;PUSH	ES
  6299                              <1> 	;PUSH	BX
  6300 00002906 53                  <1> 	push	ebx
  6301 00002907 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6302                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6303 0000290C 8A430E              <1> 	mov	al, [ebx+14]
  6304 0000290F 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6305 00002912 5B                  <1> 	pop	ebx
  6306                              <1> 	;POP	BX
  6307                              <1> 	;POP	ES
  6308 00002913 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6309                              <1> 
  6310                              <1> ;----------------------------------------
  6311                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6312                              <1> ;----------------------------------------
  6313                              <1> 
  6314                              <1> READ_DASD_TYPE:
  6315                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6316 00002918 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6317                              <1> 	;PUSH	ES
  6318 00002919 53                  <1> 	PUSH	eBX
  6319                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6320                              <1> 	;push	cs
  6321                              <1> 	;pop	ds
  6322 0000291A 66BB1000            <1>         mov	bx, KDATA
  6323 0000291E 8EDB                <1> 	mov	ds, bx
  6324                              <1> 	;mov	es, bx
  6325 00002920 C605[DF6B0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6326 00002927 8A1D[E06B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6327 0000292D 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6328 00002930 38D3                <1> 	CMP	BL,DL
  6329 00002932 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6330 00002934 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6331                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6332 00002939 8A4302              <1> 	mov	al, [ebx+2]
  6333                              <1> 	;MOV	CL,[ES:BX+14]
  6334 0000293C 8A4B0E              <1> 	mov	cl, [ebx+14]
  6335 0000293F F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6336                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6337 00002941 668B0B              <1> 	mov	cx, [ebx]
  6338                              <1> 	;
  6339                              <1> 	; 02/01/2015 
  6340                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6341                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6342 00002944 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6343                              <1> 	;
  6344 00002946 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6345 00002949 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6346 0000294C 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6347                              <1> 	;SUB	AX,AX
  6348 0000294F 28C0                <1> 	sub	al, al
  6349 00002951 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6350 00002953 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6351                              <1> 	;POP	ES
  6352 00002954 1F                  <1> 	POP	DS
  6353 00002955 F8                  <1> 	CLC				; CLEAR CARRY
  6354                              <1> 	;RETf	2
  6355 00002956 CA0400              <1> 	retf	4
  6356                              <1> RDT_NOT_PRESENT:
  6357                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6358                              <1> 	; 24/12/2021
  6359 00002959 29C0                <1> 	sub	eax, eax
  6360                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6361                              <1> 	;MOV	DX,AX
  6362 0000295B 89C1                <1> 	mov	ecx, eax
  6363 0000295D 89C2                <1> 	mov	edx, eax
  6364 0000295F EBF2                <1> 	JMP	short RDT2
  6365                              <1> 
  6366                              <1> ;----------------------------------------
  6367                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6368                              <1> ;----------------------------------------
  6369                              <1> 
  6370                              <1> GET_PARM_N:
  6371                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6372 00002961 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6373                              <1> 	;PUSH	ES
  6374 00002962 53                  <1> 	PUSH	eBX
  6375                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6376                              <1> 	;MOV	DS,AX
  6377                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6378                              <1> 	;JZ	short G0
  6379                              <1> 	;LES	BX,@HF1_TBL_VEC
  6380                              <1> 	;JMP	SHORT G1
  6381                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6382                              <1> ;G1:
  6383                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6384                              <1> 	; 22/12/2014
  6385                              <1> 	;push	cs
  6386                              <1> 	;pop	ds
  6387 00002963 66BB1000            <1> 	mov	bx, KDATA
  6388 00002967 8EDB                <1> 	mov	ds, bx
  6389                              <1> 	;mov	es, bx
  6390                              <1> 	;
  6391 00002969 80EA80              <1> 	SUB	DL,80H
  6392 0000296C 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6393 0000296F 7340                <1> 	JAE	short G4
  6394                              <1> 	;
  6395 00002971 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6396                              <1> 	; 22/12/2014
  6397 00002973 88D3                <1> 	mov	bl, dl
  6398                              <1> 	;xor	bh, bh  
  6399 00002975 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6400                              <1> 	;add	bx, HF_TBL_VEC
  6401 00002978 81C3[E46B0000]      <1> 	add	ebx, HF_TBL_VEC
  6402                              <1> 	;mov	ax, [bx+2]
  6403                              <1> 	;mov	es, ax			; dpt segment
  6404                              <1> 	;mov	bx, [bx]		; dpt offset
  6405 0000297E 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6406                              <1> 
  6407 00002980 C605[DF6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6408                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6409 00002987 668B03              <1> 	mov	ax, [ebx]
  6410                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6411 0000298A 6648                <1> 	dec	ax			; max. cylinder number
  6412 0000298C 88C5                <1> 	MOV	CH,AL
  6413 0000298E 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6414 00002992 66D1E8              <1> 	SHR	AX,1
  6415 00002995 66D1E8              <1> 	SHR	AX,1
  6416                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6417 00002998 0A430E              <1> 	or	al, [ebx+14]
  6418 0000299B 88C1                <1> 	MOV	CL,AL
  6419                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6420 0000299D 8A7302              <1> 	mov	dh, [ebx+2]
  6421 000029A0 FECE                <1> 	DEC	DH			; 0-N RANGE
  6422 000029A2 8A15[E06B0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6423                              <1> 	;SUB	AX,AX
  6424                              <1> 	; 24/12/2021
  6425 000029A8 29C0                <1> 	sub	eax, eax
  6426                              <1> 	; 27/12/2014 
  6427                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6428                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6429                              <1> 	;mov	di, bx			; HDPT offset
  6430 000029AA 89DF                <1> 	mov	edi, ebx
  6431                              <1> G5:
  6432 000029AC 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6433                              <1> 	;POP	ES
  6434 000029AD 1F                  <1> 	POP	DS
  6435                              <1> 	;RETf	2
  6436 000029AE CA0400              <1> 	retf	4
  6437                              <1> G4:
  6438 000029B1 C605[DF6B0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6439                              <1> 	; 24/12/2021
  6440 000029B8 29C0                <1> 	sub	eax, eax
  6441 000029BA B407                <1> 	MOV	AH,INIT_FAIL
  6442                              <1> 	;SUB	AL,AL
  6443                              <1> 	;SUB	DX,DX
  6444 000029BC 29D2                <1> 	sub	edx, edx
  6445                              <1> 	;SUB	CX,CX
  6446 000029BE 29C9                <1> 	sub	ecx, ecx
  6447 000029C0 F9                  <1> 	STC				; SET ERROR FLAG
  6448 000029C1 EBE9                <1> 	JMP	short G5
  6449                              <1> 
  6450                              <1> ;----------------------------------------
  6451                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6452                              <1> ;----------------------------------------
  6453                              <1> 	; 03/01/2015
  6454                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6455                              <1> 	; logical sector per logical track
  6456                              <1> 	; and logical heads - 1 would be set but
  6457                              <1> 	; it is seen as it will be good
  6458                              <1> 	; if physical parameters will be set here
  6459                              <1> 	; because, number of heads <= 16.
  6460                              <1> 	; (logical heads usually more than 16)
  6461                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6462                              <1> 	;	== INT 13h physical parameters
  6463                              <1> 
  6464                              <1> ;INIT_DRV:
  6465                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6466                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6467                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6468                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6469                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6470                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6471                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6472                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6473                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6474                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6475                              <1> ;	SUB	AX,AX
  6476                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6477                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6478                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6479                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6480                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6481                              <1> ;	CALL	CHECK_STATUS
  6482                              <1> ;INIT_EXIT:
  6483                              <1> ;	RETn
  6484                              <1> 
  6485                              <1> ; 04/01/2015
  6486                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6487                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6488                              <1> INIT_DRV:
  6489                              <1> 	;xor	ah,ah
  6490 000029C3 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6491 000029C5 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6492 000029C7 3825[F46B0000]      <1>         cmp     [LBAMode], ah   ; 0
  6493 000029CD 7702                <1> 	ja	short idrv0
  6494 000029CF B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6495                              <1> idrv0:
  6496                              <1> 	; DL = drive number (0 based)
  6497 000029D1 E8BB030000          <1> 	call	GET_VEC
  6498                              <1> 	;push	bx
  6499 000029D6 53                  <1> 	push	ebx ; 21/02/2015
  6500                              <1> 	;add	bx,ax
  6501 000029D7 01C3                <1> 	add	ebx,eax
  6502                              <1> 	;; 05/01/2015
  6503 000029D9 8A25[38660000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6504                              <1> 	;;and 	ah,1 
  6505 000029DF C0E404              <1> 	shl	ah,4
  6506 000029E2 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6507                              <1> 	;mov	al,[es:bx]
  6508 000029E5 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6509 000029E7 FEC8                <1> 	dec	al	 ; last head number 
  6510                              <1> 	;and	al,0Fh
  6511 000029E9 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6512                              <1> 	;
  6513 000029EB C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6514 000029EF 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6515                              <1> 	;pop	bx
  6516 000029F2 5B                  <1> 	pop	ebx
  6517 000029F3 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6518 000029F5 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6519 000029F7 803D[F46B0000]00    <1> 	cmp	byte [LBAMode],0
  6520 000029FE 7702                <1> 	ja	short idrv1
  6521 00002A00 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6522                              <1> idrv1:
  6523                              <1> 	;xor	ah,ah
  6524                              <1> 	;add	bx,ax
  6525 00002A02 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6526                              <1> 	;mov	al,[es:bx]
  6527                              <1> 			; sector number
  6528 00002A04 8A03                <1> 	mov	al,[ebx]
  6529 00002A06 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6530 00002A09 28C0                <1> 	sub	al,al
  6531 00002A0B 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6532 00002A0E E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6533 00002A13 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6534 00002A15 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6535 00002A1A 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6536 00002A1C E8C3020000          <1> 	call	CHECK_STATUS
  6537                              <1> INIT_EXIT:
  6538 00002A21 C3                  <1> 	RETn
  6539                              <1> 
  6540                              <1> ;----------------------------------------
  6541                              <1> ;	READ LONG	     (AH = 0AH) :
  6542                              <1> ;----------------------------------------
  6543                              <1> 
  6544                              <1> RD_LONG:
  6545                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6546 00002A22 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6547 00002A26 E9E0000000          <1>         JMP     COMMANDI
  6548                              <1> 
  6549                              <1> ;----------------------------------------
  6550                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6551                              <1> ;----------------------------------------
  6552                              <1> 
  6553                              <1> WR_LONG:
  6554                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6555 00002A2B C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6556 00002A2F E92C010000          <1>         JMP     COMMANDO
  6557                              <1> 
  6558                              <1> ;----------------------------------------
  6559                              <1> ;	SEEK		     (AH = 0CH) :
  6560                              <1> ;----------------------------------------
  6561                              <1> 
  6562                              <1> DISK_SEEK:
  6563 00002A34 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6564 00002A38 E89A010000          <1> 	CALL	COMMAND
  6565 00002A3D 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6566 00002A3F E80C020000          <1> 	CALL	_WAIT
  6567 00002A44 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6568 00002A46 E899020000          <1> 	CALL	CHECK_STATUS
  6569 00002A4B 803D[DF6B0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6570 00002A52 7507                <1> 	JNE	short DS_EXIT
  6571 00002A54 C605[DF6B0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6572                              <1> DS_EXIT:
  6573 00002A5B C3                  <1> 	RETn
  6574                              <1> 
  6575                              <1> ;----------------------------------------
  6576                              <1> ;	TEST DISK READY      (AH = 10H) :
  6577                              <1> ;----------------------------------------
  6578                              <1> 
  6579                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6580 00002A5C E82B020000          <1> 	CALL	NOT_BUSY
  6581 00002A61 751C                <1> 	JNZ	short TR_EX
  6582 00002A63 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6583 00002A66 668B15[34660000]    <1> 	MOV	DX,[HF_PORT]
  6584 00002A6D 80C206              <1> 	add	dl,6
  6585 00002A70 EE                  <1> 	OUT	DX,AL
  6586 00002A71 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6587 00002A76 7507                <1> 	JNZ	short TR_EX
  6588 00002A78 C605[DF6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6589                              <1> TR_EX:	
  6590 00002A7F C3                  <1> 	RETn
  6591                              <1> 
  6592                              <1> ;----------------------------------------
  6593                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6594                              <1> ;----------------------------------------
  6595                              <1> 
  6596                              <1> HDISK_RECAL:
  6597 00002A80 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6598 00002A84 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6599 00002A89 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6600 00002A8B E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6601 00002A90 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6602 00002A92 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6603 00002A97 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6604                              <1> RECAL_X:
  6605 00002A99 E846020000          <1> 	CALL	CHECK_STATUS
  6606 00002A9E 803D[DF6B0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6607 00002AA5 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6608 00002AA7 C605[DF6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6609                              <1> RECAL_EXIT:
  6610 00002AAE 803D[DF6B0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6611 00002AB5 C3                  <1> 	RETn
  6612                              <1> 
  6613                              <1> ;----------------------------------------
  6614                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6615                              <1> ;----------------------------------------
  6616                              <1> 
  6617                              <1> CTLR_DIAGNOSTIC:
  6618 00002AB6 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6619 00002AB7 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6620                              <1> 	;AND	AL,0BFH
  6621 00002AB9 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6622                              <1> 	;JMP	$+2
  6623                              <1> 	IODELAY
  2044 00002ABB EB00                <2>  jmp short $+2
  2045 00002ABD EB00                <2>  jmp short $+2
  6624 00002ABF E6A1                <1> 	OUT	INTB01,AL
  6625                              <1> 	IODELAY
  2044 00002AC1 EB00                <2>  jmp short $+2
  2045 00002AC3 EB00                <2>  jmp short $+2
  6626 00002AC5 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6627 00002AC7 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6628                              <1> 	;JMP	$+2
  6629                              <1> 	IODELAY
  2044 00002AC9 EB00                <2>  jmp short $+2
  2045 00002ACB EB00                <2>  jmp short $+2
  6630 00002ACD E621                <1> 	OUT	INTA01,AL
  6631 00002ACF FB                  <1> 	STI
  6632 00002AD0 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6633 00002AD5 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6634                              <1> 	;MOV	DX, HF_PORT+7
  6635 00002AD7 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6636 00002ADE 80C207              <1> 	add	dl, 7
  6637 00002AE1 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6638 00002AE3 EE                  <1> 	OUT	DX,AL
  6639 00002AE4 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6640 00002AE9 B480                <1> 	MOV	AH,TIME_OUT
  6641 00002AEB 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6642                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6643 00002AED 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6644 00002AF4 FEC2                <1> 	inc	dl
  6645 00002AF6 EC                  <1> 	IN	AL,DX
  6646 00002AF7 A2[D66B0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6647 00002AFC B400                <1> 	MOV	AH,0
  6648 00002AFE 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6649 00002B00 7402                <1> 	JE	SHORT CD_EXIT
  6650 00002B02 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6651                              <1> CD_EXIT:
  6652 00002B04 8825[DF6B0000]      <1> 	MOV	[DISK_STATUS1],AH
  6653 00002B0A C3                  <1> 	RETn
  6654                              <1> 
  6655                              <1> ;----------------------------------------
  6656                              <1> ; COMMANDI				:
  6657                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6658                              <1> ;	NSECTOR RETURNS ZERO		:
  6659                              <1> ;----------------------------------------
  6660                              <1> COMMANDI:
  6661 00002B0B E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6662 00002B10 724D                <1> 	JC	short CMD_ABORT
  6663                              <1> 	;MOV	DI,BX
  6664 00002B12 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6665 00002B14 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6666 00002B19 7544                <1> 	JNZ	short CMD_ABORT
  6667                              <1> CMD_I1:
  6668 00002B1B E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6669 00002B20 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6670                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6671 00002B22 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6672                              <1> 	;MOV	DX,HF_PORT
  6673 00002B27 668B15[34660000]    <1> 	mov	dx,[HF_PORT]
  6674 00002B2E FA                  <1> 	CLI
  6675 00002B2F FC                  <1> 	CLD
  6676 00002B30 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6677 00002B33 FB                  <1> 	STI
  6678 00002B34 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6679 00002B38 7419                <1> 	JZ	CMD_I3
  6680 00002B3A E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6681 00002B3F 721E                <1> 	JC	short TM_OUT
  6682                              <1> 	;MOV	DX,HF_PORT
  6683 00002B41 668B15[34660000]    <1> 	mov	dx,[HF_PORT]
  6684                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6685 00002B48 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6686 00002B4D EC                  <1> CMD_I2: IN	AL,DX
  6687                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6688 00002B4E 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6689 00002B50 47                  <1> 	INC	eDI
  6690 00002B51 E2FA                <1> 	LOOP	CMD_I2
  6691 00002B53 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6692 00002B58 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6693 00002B5A FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6694 00002B5D 75BC                <1> 	JNZ	SHORT CMD_I1
  6695                              <1> CMD_ABORT:
  6696 00002B5F C3                  <1> TM_OUT: RETn
  6697                              <1> 
  6698                              <1> ;----------------------------------------
  6699                              <1> ; COMMANDO				:
  6700                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6701                              <1> ;	NSECTOR RETURNS ZERO		:
  6702                              <1> ;----------------------------------------
  6703                              <1> COMMANDO:
  6704 00002B60 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6705 00002B65 72F8                <1> 	JC	short CMD_ABORT
  6706 00002B67 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6707 00002B69 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6708 00002B6E 75EF                <1> 	JNZ	short CMD_ABORT
  6709 00002B70 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6710 00002B75 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6711                              <1> CMD_O1: ;PUSH	DS
  6712                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6713                              <1> 	;POP	DS
  6714                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6715                              <1> 	;MOV	DX,HF_PORT
  6716                              <1> 	; 01/02/2015
  6717 00002B77 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6718                              <1> 	;push	es
  6719                              <1> 	;pop	ds
  6720                              <1> 	;mov	cx, 256
  6721 00002B7E B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6722 00002B83 FA                  <1> 	CLI
  6723 00002B84 FC                  <1> 	CLD
  6724 00002B85 F3666F              <1> 	REP	OUTSW
  6725 00002B88 FB                  <1> 	STI
  6726                              <1> 	;POP	DS			; RESTORE DS
  6727 00002B89 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6728 00002B8D 7419                <1> 	JZ	short CMD_O3
  6729 00002B8F E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6730 00002B94 72C9                <1> 	JC	short TM_OUT
  6731                              <1> 	;MOV	DX,HF_PORT
  6732 00002B96 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6733                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6734 00002B9D B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6735                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6736 00002BA2 8A06                <1> 	mov	al, [esi]
  6737 00002BA4 EE                  <1> 	OUT	DX,AL
  6738 00002BA5 46                  <1> 	INC	eSI
  6739 00002BA6 E2FA                <1> 	LOOP	CMD_O2
  6740                              <1> CMD_O3:
  6741 00002BA8 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6742 00002BAD 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6743 00002BAF E830010000          <1> 	CALL	CHECK_STATUS
  6744 00002BB4 75A9                <1> 	JNZ	short CMD_ABORT
  6745 00002BB6 F605[D56B0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6746 00002BBD 75B8                <1> 	JNZ	SHORT CMD_O1
  6747                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6748 00002BBF 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6749                              <1> 	;add	dl, 2
  6750 00002BC6 FEC2                <1> 	inc	dl
  6751 00002BC8 FEC2                <1> 	inc	dl
  6752 00002BCA EC                  <1> 	IN	AL,DX			;
  6753 00002BCB A8FF                <1> 	TEST	AL,0FFH 		;
  6754 00002BCD 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6755 00002BCF C605[DF6B0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6756                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6757                              <1> CMD_O4:
  6758 00002BD6 C3                  <1> 	RETn
  6759                              <1> 
  6760                              <1> ;--------------------------------------------------------
  6761                              <1> ; COMMAND						:
  6762                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6763                              <1> ; OUTPUT						:
  6764                              <1> ;	BL = STATUS					:
  6765                              <1> ;	BH = ERROR REGISTER				:
  6766                              <1> ;--------------------------------------------------------
  6767                              <1> 
  6768                              <1> COMMAND:
  6769 00002BD7 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6770                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6771                              <1> COMMAND1:
  6772                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6773 00002BD8 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6774                              <1> 	;;POP	CX
  6775 00002BDD 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6776 00002BDF 803D[DF6B0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6777                              <1> 	;JZ	short CMD_TIMEOUT
  6778                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6779                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6780 00002BE6 7507                <1> 	jne	short COMMAND4
  6781                              <1> CMD_TIMEOUT:
  6782 00002BE8 C605[DF6B0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6783                              <1> COMMAND4:
  6784 00002BEF 5B                  <1> 	POP	eBX
  6785 00002BF0 803D[DF6B0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6786 00002BF7 C3                  <1> 	RETn
  6787                              <1> COMMAND2:
  6788 00002BF8 5B                  <1> 	POP	eBX
  6789 00002BF9 57                  <1> 	PUSH	eDI
  6790 00002BFA C605[D76B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6791 00002C01 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6792 00002C02 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6793                              <1> 	;AND	AL,0BFH
  6794 00002C04 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6795                              <1> 	;JMP	$+2
  6796                              <1> 	IODELAY
  2044 00002C06 EB00                <2>  jmp short $+2
  2045 00002C08 EB00                <2>  jmp short $+2
  6797 00002C0A E6A1                <1> 	OUT	INTB01,AL
  6798 00002C0C E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6799 00002C0E 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6800                              <1> 	;JMP	$+2
  6801                              <1> 	IODELAY
  2044 00002C10 EB00                <2>  jmp short $+2
  2045 00002C12 EB00                <2>  jmp short $+2
  6802 00002C14 E621                <1> 	OUT	INTA01,AL
  6803 00002C16 FB                  <1> 	STI
  6804 00002C17 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6805                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6806 00002C19 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6807 00002C20 FEC2                <1> 	inc	dl
  6808 00002C22 F605[E16B0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6809 00002C29 7411                <1> 	JZ	short COMMAND3
  6810 00002C2B 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6811 00002C2E 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6812 00002C30 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6813 00002C32 7208                <1> 	JB	short COMMAND3
  6814 00002C34 3C40                <1> 	CMP	AL,40H
  6815 00002C36 7704                <1> 	JA	short COMMAND3
  6816 00002C38 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6817                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6818                              <1> COMMAND3:
  6819 00002C3C 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6820 00002C40 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6821                              <1> 	IODELAY
  2044 00002C41 EB00                <2>  jmp short $+2
  2045 00002C43 EB00                <2>  jmp short $+2
  6822 00002C45 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6823 00002C46 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6824 00002C48 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6825 00002C4C 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6826 00002C4E 5F                  <1> 	POP	eDI
  6827 00002C4F C3                  <1> 	RETn				; ZERO FLAG IS SET
  6828                              <1> 
  6829                              <1> ;CMD_TIMEOUT:
  6830                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6831                              <1> ;COMMAND4:
  6832                              <1> ;	POP	BX
  6833                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6834                              <1> ;	RETn
  6835                              <1> 
  6836                              <1> ;----------------------------------------
  6837                              <1> ;	WAIT FOR INTERRUPT		:
  6838                              <1> ;----------------------------------------
  6839                              <1> ;WAIT:
  6840                              <1> _WAIT:
  6841 00002C50 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6842                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6843                              <1> 	;CLC
  6844                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6845                              <1> 	;INT	15H
  6846                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6847                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6848                              <1> 
  6849                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6850                              <1> 	;; 21/02/2015
  6851                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6852                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6853 00002C51 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6854                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6855                              <1> ;-----	WAIT LOOP
  6856                              <1> 
  6857                              <1> WT1:	
  6858                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6859 00002C56 F605[D76B0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6860                              <1> 	;LOOPZ	WT1
  6861 00002C5D 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6862                              <1> 	;DEC	BL
  6863                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6864                              <1> 
  6865                              <1> WT1_hi:
  6866 00002C5F E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6867 00002C61 A810                <1> 	test	al, 10h			; transition on memory
  6868 00002C63 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6869                              <1> WT1_lo:
  6870 00002C65 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6871 00002C67 A810                <1> 	test	al, 10h			
  6872 00002C69 74FA                <1> 	jz	short WT1_lo
  6873 00002C6B E2E9                <1> 	loop	WT1
  6874                              <1> 	;;or	bl, bl
  6875                              <1> 	;;jz	short WT2	
  6876                              <1> 	;;dec	bl
  6877                              <1> 	;;jmp	short WT1
  6878                              <1> 	;dec	bl
  6879                              <1> 	;jnz	short WT1	
  6880                              <1> 
  6881 00002C6D C605[DF6B0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6882 00002C74 EB0E                <1> 	JMP	SHORT WT4
  6883 00002C76 C605[DF6B0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6884 00002C7D C605[D76B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6885 00002C84 803D[DF6B0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6886 00002C8B C3                  <1> 	RETn
  6887                              <1> 
  6888                              <1> ;----------------------------------------
  6889                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6890                              <1> ;----------------------------------------
  6891                              <1> NOT_BUSY:
  6892 00002C8C FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6893                              <1> 	;PUSH	eBX
  6894                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6895 00002C8D 668B15[34660000]    <1> 	mov	DX, [HF_PORT]
  6896 00002C94 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6897                              <1> 	;MOV	BL,DELAY_1
  6898                              <1> 					; wait for 10 seconds
  6899                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6900                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6901                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6902 00002C97 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6903                              <1> 	;
  6904                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6905                              <1> NB1:	
  6906 00002C9C EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6907                              <1> 	;TEST	AL,ST_BUSY
  6908 00002C9D 2480                <1> 	and	al, ST_BUSY
  6909                              <1> 	;LOOPNZ	NB1
  6910 00002C9F 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6911                              <1> 	;DEC	BL			
  6912                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6913                              <1> 
  6914 00002CA1 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  6915 00002CA3 A810                <1> 	TEST	AL,010H			; transition on memory
  6916 00002CA5 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  6917 00002CA7 E461                <1> NB1_lo: IN	AL,SYS1
  6918 00002CA9 A810                <1> 	TEST	AL,010H
  6919 00002CAB 74FA                <1> 	JZ	short NB1_lo
  6920 00002CAD E2ED                <1> 	LOOP	NB1
  6921                              <1> 	;dec	bl
  6922                              <1> 	;jnz	short NB1
  6923                              <1> 	;
  6924                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6925                              <1> ;;	jb	short NB1
  6926                              <1> 	;
  6927                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  6928                              <1> 	;JMP	SHORT NB3
  6929 00002CAF B080                <1> 	mov	al, TIME_OUT
  6930                              <1> NB2:	
  6931                              <1> 	;MOV	byte [DISK_STATUS1],0
  6932                              <1> ;NB3:	
  6933                              <1> 	;POP	eBX
  6934 00002CB1 A2[DF6B0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  6935                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6936 00002CB6 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  6937 00002CB8 C3                  <1> 	RETn
  6938                              <1> 
  6939                              <1> ;----------------------------------------
  6940                              <1> ;	WAIT FOR DATA REQUEST		:
  6941                              <1> ;----------------------------------------
  6942                              <1> WAIT_DRQ:
  6943                              <1> 	;MOV	CX,DELAY_3
  6944                              <1> 	;MOV	DX,HF_PORT+7
  6945 00002CB9 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6946 00002CC0 80C207              <1> 	add	dl, 7
  6947                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  6948                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  6949                              <1> 					; (but it is written as 2000
  6950                              <1> 					; micro seconds in ATORGS.ASM file
  6951                              <1> 					; of Award Bios - 1999, D1A0622)
  6952 00002CC3 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6953 00002CC8 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  6954 00002CC9 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  6955 00002CCB 7516                <1> 	JNZ	short WQ_OK
  6956                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6957                              <1> WQ_hi:	
  6958 00002CCD E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  6959 00002CCF A810                <1> 	TEST	AL,010H			; transition on memory
  6960 00002CD1 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  6961 00002CD3 E461                <1> WQ_lo:  IN      AL,SYS1
  6962 00002CD5 A810                <1> 	TEST	AL,010H
  6963 00002CD7 74FA                <1> 	JZ	SHORT WQ_lo
  6964 00002CD9 E2ED                <1> 	LOOP	WQ_1
  6965                              <1> 
  6966 00002CDB C605[DF6B0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  6967 00002CE2 F9                  <1> 	STC
  6968                              <1> WQ_OK:
  6969 00002CE3 C3                  <1> 	RETn
  6970                              <1> ;WQ_OK:	;CLC
  6971                              <1> ;	RETn
  6972                              <1> 
  6973                              <1> ;----------------------------------------
  6974                              <1> ;	CHECK FIXED DISK STATUS 	:
  6975                              <1> ;----------------------------------------
  6976                              <1> CHECK_STATUS:
  6977 00002CE4 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  6978 00002CE9 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  6979 00002CEB A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  6980 00002CED 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  6981 00002CEF E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  6982                              <1> CHECK_S1:
  6983 00002CF4 803D[DF6B0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  6984 00002CFB C3                  <1> 	RETn
  6985                              <1> 
  6986                              <1> ;----------------------------------------
  6987                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  6988                              <1> ;----------------------------------------
  6989                              <1> CHECK_ST:
  6990                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  6991 00002CFC 668B15[34660000]    <1> 	mov	dx, [HF_PORT]
  6992 00002D03 80C207              <1> 	add	dl, 7
  6993 00002D06 EC                  <1> 	IN	AL,DX
  6994 00002D07 A2[D56B0000]        <1> 	MOV	[HF_STATUS],AL
  6995 00002D0C B400                <1> 	MOV	AH,0
  6996 00002D0E A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  6997 00002D10 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  6998 00002D12 B4CC                <1> 	MOV	AH,WRITE_FAULT
  6999 00002D14 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7000 00002D16 7514                <1> 	JNZ	short CKST_EXIT
  7001 00002D18 B4AA                <1> 	MOV	AH,NOT_RDY
  7002 00002D1A A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7003 00002D1C 740E                <1> 	JZ	short CKST_EXIT
  7004 00002D1E B440                <1> 	MOV	AH,BAD_SEEK
  7005 00002D20 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7006 00002D22 7408                <1> 	JZ	short CKST_EXIT
  7007 00002D24 B411                <1> 	MOV	AH,DATA_CORRECTED
  7008 00002D26 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7009 00002D28 7502                <1> 	JNZ	short CKST_EXIT
  7010 00002D2A B400                <1> 	MOV	AH,0
  7011                              <1> CKST_EXIT:
  7012 00002D2C 8825[DF6B0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7013 00002D32 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7014 00002D35 7403                <1> 	JZ	short CKST_EX1
  7015 00002D37 80FC00              <1> 	CMP	AH,0
  7016                              <1> CKST_EX1:
  7017 00002D3A C3                  <1> 	RETn
  7018                              <1> 
  7019                              <1> ;----------------------------------------
  7020                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7021                              <1> ;----------------------------------------
  7022                              <1> CHECK_ER:
  7023                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7024 00002D3B 668B15[34660000]    <1> 	mov	dx, [HF_PORT]		;
  7025 00002D42 FEC2                <1> 	inc	dl
  7026 00002D44 EC                  <1> 	IN	AL,DX
  7027 00002D45 A2[D66B0000]        <1> 	MOV	[HF_ERROR],AL
  7028 00002D4A 53                  <1> 	PUSH	eBX ; 21/02/2015
  7029 00002D4B B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7030 00002D50 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7031 00002D52 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7032 00002D54 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7033 00002D56 BB[28660000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7034 00002D5B 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7035                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7036                              <1> 	;mov	ah, [bx]
  7037 00002D5D 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7038 00002D5F 8825[DF6B0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7039 00002D65 5B                  <1> 	POP	eBX
  7040 00002D66 80FC00              <1> 	CMP	AH,0
  7041 00002D69 C3                  <1> 	RETn
  7042                              <1> 
  7043                              <1> ;--------------------------------------------------------
  7044                              <1> ; CHECK_DMA						:
  7045                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7046                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7047                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7048                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7049                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7050                              <1> ;  -ERROR OTHERWISE					:
  7051                              <1> ;--------------------------------------------------------
  7052                              <1> CHECK_DMA:
  7053                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7054                              <1> 	; 24/12/2021
  7055 00002D6A 50                  <1> 	push	eax
  7056 00002D6B 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7057 00002D6F F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7058 00002D73 7404                <1> 	JZ	short CKD1
  7059 00002D75 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7060 00002D79 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7061 00002D7C 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7062 00002D7E 7207                <1> 	JB	short CKDERR		; TOO MANY
  7063 00002D80 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7064 00002D82 7203                <1> 	JB	short CKDERR		; ERROR
  7065 00002D84 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7066                              <1> 	;POP	AX
  7067                              <1> 	; 24/12/2021
  7068 00002D85 58                  <1> 	pop	eax
  7069 00002D86 C3                  <1> 	RETn				; NORMAL RETURN
  7070 00002D87 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7071 00002D88 C605[DF6B0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7072                              <1> 	;POP	AX
  7073                              <1> 	; 24/12/2021
  7074 00002D8F 58                  <1> 	pop	eax	
  7075 00002D90 C3                  <1> 	RETn
  7076                              <1> 
  7077                              <1> ;----------------------------------------
  7078                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7079                              <1> ;----------------------------------------
  7080                              <1> 					
  7081                              <1> ; INPUT -> DL = 0 based drive number
  7082                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7083                              <1> 
  7084                              <1> GET_VEC:
  7085                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7086                              <1> 	;MOV	ES,AX
  7087                              <1> 	;TEST	DL,1
  7088                              <1> 	;JZ	short GV_0
  7089                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7090                              <1> ;	JMP	SHORT GV_EXIT
  7091                              <1> ;GV_0:
  7092                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7093                              <1> ;
  7094                              <1> 	;xor	bh, bh
  7095 00002D91 31DB                <1> 	xor	ebx, ebx
  7096 00002D93 88D3                <1> 	mov	bl, dl
  7097                              <1> 	;;02/01/2015
  7098                              <1> 	;;shl	bl, 1			; port address offset
  7099                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7100                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7101 00002D95 C0E302              <1> 	shl	bl, 2	;;
  7102                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7103 00002D98 81C3[E46B0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7104                              <1> 	;push	word [bx+2]		; dpt segment
  7105                              <1> 	;pop	es
  7106                              <1> 	;mov	bx, [bx]		; dpt offset
  7107 00002D9E 8B1B                <1> 	mov	ebx, [ebx]		
  7108                              <1> ;GV_EXIT:
  7109 00002DA0 C3                  <1> 	RETn
  7110                              <1> 
  7111                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7112                              <1> hdc1_int: ; 21/02/2015
  7113                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7114                              <1> ;								:
  7115                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7116                              <1> ;								:
  7117                              <1> ;----------------------------------------------------------------
  7118                              <1> 
  7119                              <1> ; 22/12/2014
  7120                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7121                              <1> ;	 '11/15/85'
  7122                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7123                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7124                              <1> 
  7125                              <1> ;int_76h:
  7126                              <1> HD_INT:
  7127                              <1> 	;push	ax
  7128                              <1> 	; 24/12/2021
  7129 00002DA1 50                  <1> 	push	eax
  7130 00002DA2 1E                  <1> 	push	ds
  7131                              <1> 	;CALL	DDS
  7132                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7133 00002DA3 66B81000            <1> 	mov	ax, KDATA
  7134 00002DA7 8ED8                <1> 	mov 	ds, ax
  7135                              <1> 	;
  7136                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7137                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7138 00002DA9 C605[D76B0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7139                              <1> 	;
  7140                              <1> 	;push	dx
  7141                              <1> 	; 24/12/2021
  7142 00002DB0 52                  <1> 	push	edx
  7143 00002DB1 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7144                              <1> 					; Clear Controller
  7145                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7146 00002DB5 EC                  <1> 	in	al, dx			;
  7147                              <1> 	;pop	dx
  7148                              <1> 	; 24/12/2021
  7149 00002DB6 5A                  <1> 	pop	edx
  7150                              <1> 	NEWIODELAY
  2049 00002DB7 E6EB                <2>  out 0EBh,al
  7151                              <1> 	;
  7152 00002DB9 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7153 00002DBB E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7154                              <1> 	;JMP	$+2			; WAIT
  7155                              <1> 	NEWIODELAY
  2049 00002DBD E6EB                <2>  out 0EBh,al
  7156 00002DBF E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7157 00002DC1 1F                  <1> 	pop	ds
  7158                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7159                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7160                              <1> 	;INT	15H			;  INTERRUPT
  7161                              <1> irq15_iret: ; 25/02/2015
  7162                              <1> 	;pop	ax
  7163                              <1> 	; 24/12/2021
  7164 00002DC2 58                  <1> 	pop	eax
  7165 00002DC3 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7166                              <1> 
  7167                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7168                              <1> hdc2_int: ; 21/02/2015
  7169                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7170                              <1> ;								:
  7171                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7172                              <1> ;								:
  7173                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7174                              <1> 
  7175                              <1> ;int_77h:
  7176                              <1> HD1_INT:
  7177                              <1> 	;push	ax
  7178                              <1> 	; 24/12/2021
  7179 00002DC4 50                  <1> 	push	eax
  7180                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7181                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7182 00002DC5 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7183 00002DC7 E6A0                <1> 	out	0A0h, al
  7184 00002DC9 EB00                <1>         jmp short $+2
  7185 00002DCB EB00                <1> 	jmp short $+2
  7186 00002DCD E4A0                <1> 	in	al, 0A0h
  7187 00002DCF 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7188 00002DD1 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7189                              <1> 	;
  7190 00002DD3 1E                  <1> 	push	ds
  7191                              <1> 	;CALL	DDS
  7192                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7193 00002DD4 66B81000            <1> 	mov	ax, KDATA
  7194 00002DD8 8ED8                <1> 	mov 	ds, ax
  7195                              <1> 	;
  7196                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7197                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7198 00002DDA 800D[D76B0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7199                              <1> 	;
  7200                              <1> 	;push	dx
  7201                              <1> 	; 24/12/2021
  7202 00002DE1 52                  <1> 	push	edx
  7203 00002DE2 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7204                              <1> 					; Clear Controller (Award BIOS 1999)
  7205 00002DE6 EBCD                <1> 	jmp	short Clear_IRQ1415
  7206                              <1> 
  7207                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7208                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7209                              <1> 
  7210                              <1> ;////////////////////////////////////////////////////////////////////
  7211                              <1> ;; END OF DISK I/O SYTEM ///
  1986                                  %include 'memory.inc'  ; 09/03/2015
  1987                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  1988                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.18) - MEMORY.INC
  1989                              <1> ; Last Modification: 03/02/2022 [ 31/12/2021 (Retro UNIX 386 v1.1) ]
  1990                              <1> ;
  1991                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  1992                              <1> 
  1993                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.1 - MEMORY.INC (31/12/2021)
  1994                              <1> 
  1995                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  1996                              <1> 
  1997                              <1> ;;04/11/2014 (unix386.s)	
  1998                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  1999                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2000                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2001                              <1> ;;
  2002                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2003                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2004                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2005                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2006                              <1> 
  2007                              <1> ; 27/04/2015
  2008                              <1> ; 09/03/2015
  2009                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2010                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2011                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2012                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2013                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2014                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2015                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2016                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2017                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2018                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2019                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2020                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2021                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2022                              <1> SWP_DISK_READ_ERR 	   equ 40
  2023                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2024                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2025                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2026                              <1> SWP_DISK_WRITE_ERR         equ 44
  2027                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2028                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2029                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2030                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2031                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2032                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2033                              <1> 					; (Indicates that the page is not allocated
  2034                              <1> 					; for the process, it is a shared or system
  2035                              <1>                                         ; page, it must not be deallocated!)
  2036                              <1> ; 14/12/2020
  2037                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2038                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2039                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2040                              <1> 				; (Out of memory allocation table)	
  2041                              <1> ;
  2042                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2043                              <1> ;;
  2044                              <1> ;; 10/10/2014
  2045                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2046                              <1> ;;
  2047                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2048                              <1> ;;	(virtual address = physical address)
  2049                              <1> ;; KERNEL PAGE TABLES:
  2050                              <1> ;;	Kernel page directory and all page tables are
  2051                              <1> ;;	on memory as initialized, as equal to physical memory
  2052                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2053                              <1> ;;
  2054                              <1> ;;	what for: User pages may be swapped out, when accessing
  2055                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2056                              <1> ;;	kernel would have to swap it in! But it is also may be
  2057                              <1> ;;	in use by a user process. (In system/kernel mode
  2058                              <1> ;;	kernel can access all memory pages even if they are
  2059                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2060                              <1> ;;	cause conflicts.) 
  2061                              <1> ;;	
  2062                              <1> ;;	As result of these conditions,
  2063                              <1> ;;	all kernel pages must be initialized as equal to 
  2064                              <1> ;;	physical layout for preventing page faults. 
  2065                              <1> ;;	Also, calling "allocate page" procedure after
  2066                              <1> ;;	a page fault can cause another page fault (double fault)
  2067                              <1> ;;	if all kernel page tables would not be initialized.
  2068                              <1> ;;
  2069                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2070                              <1> ;;	memory allocation table. (double word aligned)
  2071                              <1> ;;
  2072                              <1> ;;	[next_page] = first/next free space to be searched
  2073                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2074                              <1> ;;
  2075                              <1> ;;	[last_page] = End of memory (users space), as offset
  2076                              <1> ;;	to memory allocation table. (double word aligned)
  2077                              <1> ;;
  2078                              <1> ;; USER PAGE TABLES:
  2079                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2080                              <1> ;;		'ready only' marked copies of the 
  2081                              <1> ;;		parent process's page table entries (for
  2082                              <1> ;;		same physical memory).
  2083                              <1> ;;		(A page will be copied to a new page after
  2084                              <1> ;;		 if it causes R/W page fault.)
  2085                              <1> ;;
  2086                              <1> ;;	Every user process has own (different)
  2087                              <1> ;;	page directory and page tables.	
  2088                              <1> ;;
  2089                              <1> ;;	Code starts at virtual address 0, always.
  2090                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2091                              <1> ;;	(Programs can be written/developed as simple
  2092                              <1> ;;	 flat memory programs.)
  2093                              <1> ;;
  2094                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2095                              <1> ;;	Memory page will be allocated by kernel only 
  2096                              <1> ;;		(in kernel/system mode only).
  2097                              <1> ;;	* After a
  2098                              <1> ;;	  - 'not present' page fault
  2099                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2100                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2101                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2102                              <1> ;;	  request by running process.
  2103                              <1> ;;	* While creating a process, allocating a new buffer,
  2104                              <1> ;;	  new page tables etc.
  2105                              <1> ;;
  2106                              <1> ;;	At first,
  2107                              <1> ;;	- 'allocate page' procedure will be called;
  2108                              <1> ;,	   if it will return with a valid (>0) physical address
  2109                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2110                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2111                              <1> ;;	- 'allocate page' will be called for allocating page
  2112                              <1> ;;	   directory, page table and running space (data/code).
  2113                              <1> ;;	- every successful 'allocate page' call will decrease
  2114                              <1> ;;	  'free_pages' count (pointer).
  2115                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2116                              <1> ;;	  if 'free_pages' points to a ZERO.
  2117                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2118                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2119                              <1> ;;	  error except errors caused by attribute conflicts.
  2120                              <1> ;;	 (swapper functions)	 
  2121                              <1> ;;					
  2122                              <1> ;;	At second,
  2123                              <1> ;;	- page directory entry will be updated then page table
  2124                              <1> ;;	  entry will be updated.		
  2125                              <1> ;;
  2126                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2127                              <1> ;;	- M.A.T. has a size according to available memory as
  2128                              <1> ;;	  follows:
  2129                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2130                              <1> ;;		  - a bit with value of 0 means allocated page
  2131                              <1> ;;		  - a bit with value of 1 means a free page
  2132                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2133                              <1> ;;	  depending on M.A.T.
  2134                              <1> ;;		(NOTE: Free page count will not be checked
  2135                              <1> ;;		again -on M.A.T.- after initialization. 
  2136                              <1> ;;		Kernel will trust on initial count.)
  2137                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2138                              <1> ;;	  and it will be increased by deallocation procedures.
  2139                              <1> ;;	
  2140                              <1> ;;	- Available memory will be calculated during
  2141                              <1> ;;	  the kernel's initialization stage (in real mode).
  2142                              <1> ;;	  Memory allocation table and kernel page tables 
  2143                              <1> ;;	  will be formatted/sized as result of available
  2144                              <1> ;;	  memory calculation before paging is enabled.
  2145                              <1> ;;
  2146                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2147                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2148                              <1> ;;	- Memory allocation for kernel page directory size 
  2149                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2150                              <1> ;;	  for page tables)
  2151                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2152                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2153                              <1> ;;	- User (available) space will be started 
  2154                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2155                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2156                              <1> ;;	  memory allocation table and kernel's page directory
  2157                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2158                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2159                              <1> ;; 	  for buffers.
  2160                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2161                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2162                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2163                              <1> ;;
  2164                              <1> ;; For 1GB Available Memory:
  2165                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2166                              <1> ;;	- Memory allocation for kernel page directory size 
  2167                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2168                              <1> ;;	  for page tables)
  2169                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2170                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2171                              <1> ;;	- User (available) space will be started 
  2172                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2173                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2174                              <1> ;;	  memory allocation table and kernel's page directory
  2175                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2176                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2177                              <1> ;; 	  for buffers.
  2178                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2179                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2180                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2181                              <1> ;;
  2182                              <1> ;;
  2183                              <1> 
  2184                              <1> ;;************************************************************************************
  2185                              <1> ;; 
  2186                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2187                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2188                              <1> 
  2189                              <1> ;; Main factor: "sys fork" system call 
  2190                              <1> ;;	
  2191                              <1> ;; 		FORK
  2192                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2193                              <1> ;;  writable pages ---->|
  2194                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2195                              <1> ;; 
  2196                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2197                              <1> ;; 
  2198                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2199                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2200                              <1> ;;       -while R/W bit is 0-. 
  2201                              <1> ;; 
  2202                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2203                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2204                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2205                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2206                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2207                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2208                              <1> ;; 
  2209                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2210                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2211                              <1> ;;   Parent's PTE attributes are not changed.
  2212                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2213                              <1> ;;    destroy/mix previous fork result).
  2214                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2215                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2216                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2217                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2218                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2219                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2220                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2221                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2222                              <1> ;; 
  2223                              <1> ;; !? WHAT FOR (duplication after duplication):
  2224                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2225                              <1> ;; program/executable code continues from specified location as child process, 
  2226                              <1> ;; returns back previous code location as parent process, every child after 
  2227                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2228                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2229                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2230                              <1> ;; was copied to child's process segment (all of code and data) according to
  2231                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2232                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2233                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2234                              <1> ;; (complete running image of parent process) to the child process; 
  2235                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2236                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2237                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2238                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2239                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2240                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2241                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2242                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2243                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2244                              <1> ;; for sharing same read only pages between parent and child processes.
  2245                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2246                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2247                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2248                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2249                              <1> ;; -deallocation problem-.
  2250                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2251                              <1> ;; 
  2252                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2253                              <1> ;; # Page fault handler will do those:
  2254                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2255                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2256                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2257                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2258                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2259                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2260                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2261                              <1> ;;     to child process.)	
  2262                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2263                              <1> ;; # Page fault handler will do those:
  2264                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2265                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2266                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2267                              <1> ;;     address or not. 
  2268                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2269                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2270                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2271                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2272                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2273                              <1> ;; 
  2274                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2275                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2276                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2277                              <1> ;;       duplication method details, it is not possible multiple child processes
  2278                              <1> ;;       were using same page with duplicated PTEs.
  2279                              <1> ;; 
  2280                              <1> ;;************************************************************************************   
  2281                              <1> 
  2282                              <1> ;; 08/10/2014
  2283                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2284                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2285                              <1> 
  2286                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2287                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2288                              <1> ;; (25/08/2014, Revision: 5057) file 
  2289                              <1> ;; by KolibriOS Team (2004-2012)
  2290                              <1> 
  2291                              <1> allocate_page:
  2292                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2293                              <1> 	; 01/07/2015
  2294                              <1> 	; 05/05/2015
  2295                              <1> 	; 30/04/2015
  2296                              <1> 	; 16/10/2014
  2297                              <1> 	; 08/10/2014
  2298                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2299                              <1> 	;
  2300                              <1> 	; INPUT -> none
  2301                              <1> 	;
  2302                              <1> 	; OUTPUT ->
  2303                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2304                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2305                              <1> 	;
  2306                              <1> 	;	CF = 1 and EAX = 0 
  2307                              <1> 	; 		   if there is not a free page to be allocated	
  2308                              <1> 	;
  2309                              <1> 	; Modified Registers -> none (except EAX)
  2310                              <1> 	;
  2311 00002DE8 A1[506B0000]        <1> 	mov	eax, [free_pages]
  2312 00002DED 21C0                <1> 	and	eax, eax
  2313 00002DEF 7438                <1> 	jz	short out_of_memory
  2314                              <1> 	;
  2315 00002DF1 53                  <1> 	push	ebx
  2316 00002DF2 51                  <1> 	push	ecx
  2317                              <1> 	;
  2318 00002DF3 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2319 00002DF8 89D9                <1> 	mov	ecx, ebx
  2320                              <1>  				     ; NOTE: 32 (first_page) is initial
  2321                              <1> 				     ; value of [next_page].
  2322                              <1> 				     ; It points to the first available
  2323                              <1> 				     ; page block for users (ring 3) ...	
  2324                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2325                              <1> 				     ; (at the of the first 4 MB)		
  2326 00002DFA 031D[546B0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2327                              <1> 				 ; next_free_page >> 5
  2328 00002E00 030D[586B0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2329                              <1> 				 ; (total_pages - 1) >> 5
  2330                              <1> al_p_scan:
  2331 00002E06 39CB                <1> 	cmp	ebx, ecx
  2332 00002E08 770A                <1> 	ja	short al_p_notfound
  2333                              <1> 	;
  2334                              <1> 	; 01/07/2015
  2335                              <1> 	; AMD64 Architecture Programmers Manual
  2336                              <1> 	; Volume 3:
  2337                              <1> 	; General-Purpose and System Instructions
  2338                              <1> 	;
  2339                              <1> 	; BSF - Bit Scan Forward
  2340                              <1> 	;
  2341                              <1> 	;   Searches the value in a register or a memory location
  2342                              <1> 	;   (second operand) for the least-significant set bit. 
  2343                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2344                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2345                              <1> 	;   register (first operand). If the second operand contains 0, 
  2346                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2347                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2348                              <1> 	;   of the searched value
  2349                              <1> 	;
  2350 00002E0A 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2351                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2352                              <1> 			   ; loads the destination with an index to
  2353                              <1> 			   ; first set bit. (0 -> 31) 
  2354                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2355 00002E0D 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2356                              <1> 			 ;
  2357                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2358                              <1> 			 ;	  with value of 1 means 
  2359                              <1> 			 ;	  the corresponding page is free 
  2360                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2361 00002E0F 83C304              <1> 	add	ebx, 4
  2362                              <1> 			 ; We return back for searching next page block
  2363                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2364                              <1> 			 ;	 we always will find at least 1 free page here.
  2365 00002E12 EBF2                <1>         jmp     short al_p_scan
  2366                              <1> 	;
  2367                              <1> al_p_notfound:
  2368 00002E14 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2369 00002E1A 890D[546B0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2370                              <1> 				 ; (deallocate_page procedure will change it)
  2371 00002E20 31C0                <1> 	xor	eax, eax
  2372 00002E22 A3[506B0000]        <1> 	mov	[free_pages], eax ; 0
  2373 00002E27 59                  <1> 	pop	ecx
  2374 00002E28 5B                  <1> 	pop	ebx
  2375                              <1> 	;
  2376                              <1> ; 24/12/2021
  2377                              <1> ; ('swap_out' procedure call is disabled)
  2378                              <1> 
  2379                              <1> out_of_memory:
  2380                              <1> ;	call	swap_out
  2381                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2382                              <1> ;	;
  2383                              <1> ;	sub 	eax, eax ; 0
  2384 00002E29 F9                  <1> 	stc
  2385 00002E2A C3                  <1> 	retn
  2386                              <1> 
  2387                              <1> al_p_found:
  2388 00002E2B 89D9                <1> 	mov	ecx, ebx
  2389 00002E2D 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2390 00002E33 890D[546B0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2391                              <1> 				 ; address/offset (to the next)
  2392 00002E39 FF0D[506B0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2393                              <1> 	;
  2394 00002E3F 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2395                              <1> 				 ; is copied into the Carry Flag and then cleared
  2396                              <1> 				 ; in the destination.
  2397                              <1> 				 ;
  2398                              <1> 				 ; Reset the bit which is corresponding to the 
  2399                              <1> 				 ; (just) allocated page.
  2400                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2401 00002E42 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2402 00002E45 01C8                <1> 	add	eax, ecx	 ; = page number
  2403 00002E47 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2404                              <1> 	; EAX = physical address of memory page
  2405                              <1> 	;
  2406                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2407                              <1> 	;       according to this EAX value...
  2408 00002E4A 59                  <1> 	pop	ecx
  2409 00002E4B 5B                  <1> 	pop	ebx
  2410                              <1> al_p_ok:
  2411 00002E4C C3                  <1> 	retn
  2412                              <1> 
  2413                              <1> make_page_dir:
  2414                              <1> 	; 18/04/2015
  2415                              <1> 	; 12/04/2015
  2416                              <1> 	; 23/10/2014
  2417                              <1> 	; 16/10/2014
  2418                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2419                              <1> 	;
  2420                              <1> 	; INPUT ->
  2421                              <1> 	;	none
  2422                              <1> 	; OUTPUT ->
  2423                              <1> 	;	(EAX = 0)
  2424                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2425                              <1> 	;	cf = 0 ->
  2426                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2427                              <1> 	;		  process/user.
  2428                              <1> 	;
  2429                              <1> 	; Modified Registers -> EAX
  2430                              <1> 	;
  2431 00002E4D E896FFFFFF          <1> 	call	allocate_page
  2432 00002E52 7216                <1> 	jc	short mkpd_error
  2433                              <1> 	;
  2434 00002E54 A3[4B6F0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2435                              <1> 				  ; (Physical address)
  2436                              <1> clear_page:
  2437                              <1> 	; 18/04/2015
  2438                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2439                              <1> 	;
  2440                              <1> 	; INPUT ->
  2441                              <1> 	;	EAX = physical address of the page
  2442                              <1> 	; OUTPUT ->
  2443                              <1> 	;	all bytes of the page will be cleared
  2444                              <1> 	;
  2445                              <1> 	; Modified Registers -> none
  2446                              <1> 	;
  2447 00002E59 57                  <1> 	push	edi
  2448 00002E5A 51                  <1> 	push	ecx
  2449 00002E5B 50                  <1> 	push	eax
  2450 00002E5C B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2451 00002E61 89C7                <1> 	mov	edi, eax
  2452 00002E63 31C0                <1> 	xor	eax, eax
  2453 00002E65 F3AB                <1> 	rep	stosd
  2454 00002E67 58                  <1> 	pop	eax
  2455 00002E68 59                  <1> 	pop	ecx
  2456 00002E69 5F                  <1> 	pop	edi
  2457                              <1> mkpd_error:
  2458                              <1> mkpt_error:
  2459 00002E6A C3                  <1> 	retn
  2460                              <1> 
  2461                              <1> make_page_table:
  2462                              <1> 	; 23/06/2015
  2463                              <1> 	; 18/04/2015
  2464                              <1> 	; 12/04/2015
  2465                              <1> 	; 16/10/2014
  2466                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2467                              <1> 	;
  2468                              <1> 	; INPUT ->
  2469                              <1> 	;	EBX = virtual (linear) address
  2470                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2471                              <1> 	;	      (higher 20 bits must be ZERO)
  2472                              <1> 	;	      (bit 0 must be 1)	 
  2473                              <1> 	;	u.pgdir = page directory (physical) address
  2474                              <1> 	; OUTPUT ->
  2475                              <1> 	;	EDX = Page directory entry address
  2476                              <1> 	;	EAX = Page table address
  2477                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2478                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2479                              <1> 	;
  2480                              <1> 	; Modified Registers -> EAX, EDX
  2481                              <1> 	;
  2482 00002E6B E878FFFFFF          <1> 	call	allocate_page
  2483 00002E70 72F8                <1> 	jc	short mkpt_error
  2484 00002E72 E811000000          <1> 	call	set_pde	
  2485 00002E77 EBE0                <1> 	jmp	short clear_page
  2486                              <1> 
  2487                              <1> make_page:
  2488                              <1> 	; 24/07/2015
  2489                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2490                              <1> 	;
  2491                              <1> 	; INPUT ->
  2492                              <1> 	;	EBX = virtual (linear) address
  2493                              <1> 	;	ECX = page attributes (lower 12 bits)
  2494                              <1> 	;	      (higher 20 bits must be ZERO)
  2495                              <1> 	;	      (bit 0 must be 1)	 
  2496                              <1> 	;	u.pgdir = page directory (physical) address
  2497                              <1> 	; OUTPUT ->
  2498                              <1> 	;	EBX = Virtual address
  2499                              <1> 	;	(EDX = PTE value)
  2500                              <1> 	;	EAX = Physical address
  2501                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2502                              <1> 	;
  2503                              <1> 	; Modified Registers -> EAX, EDX
  2504                              <1> 	;
  2505 00002E79 E86AFFFFFF          <1> 	call	allocate_page
  2506 00002E7E 7207                <1> 	jc	short mkp_err
  2507 00002E80 E821000000          <1> 	call	set_pte	
  2508 00002E85 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2509                              <1> mkp_err:
  2510 00002E87 C3                  <1> 	retn
  2511                              <1> 
  2512                              <1> set_pde:	; Set page directory entry (PDE)
  2513                              <1> 	; 20/07/2015
  2514                              <1> 	; 18/04/2015
  2515                              <1> 	; 12/04/2015
  2516                              <1> 	; 23/10/2014
  2517                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2518                              <1> 	;
  2519                              <1> 	; INPUT ->
  2520                              <1> 	;	EAX = physical address
  2521                              <1> 	;	      (use present value if EAX = 0)
  2522                              <1> 	;	EBX = virtual (linear) address
  2523                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2524                              <1> 	;	      (higher 20 bits must be ZERO)
  2525                              <1> 	;	      (bit 0 must be 1)	 
  2526                              <1> 	;	u.pgdir = page directory (physical) address
  2527                              <1> 	; OUTPUT ->
  2528                              <1> 	;	EDX = PDE address
  2529                              <1> 	;	EAX = page table address (physical)
  2530                              <1> 	;	;(CF=1 -> Invalid page address)
  2531                              <1> 	;
  2532                              <1> 	; Modified Registers -> EDX
  2533                              <1> 	;
  2534 00002E88 89DA                <1> 	mov	edx, ebx
  2535 00002E8A C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2536 00002E8D C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2537 00002E90 0315[4B6F0000]      <1> 	add	edx, [u.pgdir]
  2538                              <1> 	;
  2539 00002E96 21C0                <1> 	and	eax, eax
  2540 00002E98 7506                <1> 	jnz	short spde_1
  2541                              <1> 	;
  2542 00002E9A 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2543                              <1> 	;test	al, 1
  2544                              <1> 	;jz	short spde_2
  2545 00002E9C 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2546                              <1> spde_1:
  2547                              <1> 	;and	cx, 0FFFh
  2548 00002EA0 8902                <1> 	mov	[edx], eax
  2549 00002EA2 66090A              <1> 	or	[edx], cx
  2550 00002EA5 C3                  <1> 	retn
  2551                              <1> ;spde_2: ; error
  2552                              <1> ;	stc
  2553                              <1> ;	retn
  2554                              <1> 
  2555                              <1> set_pte:	; Set page table entry (PTE)
  2556                              <1> 	; 24/07/2015
  2557                              <1> 	; 20/07/2015
  2558                              <1> 	; 23/06/2015
  2559                              <1> 	; 18/04/2015
  2560                              <1> 	; 12/04/2015
  2561                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2562                              <1> 	;
  2563                              <1> 	; INPUT ->
  2564                              <1> 	;	EAX = physical page address
  2565                              <1> 	;	      (use present value if EAX = 0)
  2566                              <1> 	;	EBX = virtual (linear) address
  2567                              <1> 	;	ECX = page attributes (lower 12 bits)
  2568                              <1> 	;	      (higher 20 bits must be ZERO)
  2569                              <1> 	;	      (bit 0 must be 1)	 
  2570                              <1> 	;	u.pgdir = page directory (physical) address
  2571                              <1> 	; OUTPUT ->
  2572                              <1> 	;	EAX = physical page address
  2573                              <1> 	;	(EDX = PTE value)
  2574                              <1> 	;	EBX = virtual address
  2575                              <1> 	;
  2576                              <1> 	;	CF = 1 -> error
  2577                              <1> 	;
  2578                              <1> 	; Modified Registers -> EAX, EDX
  2579                              <1> 	;
  2580 00002EA6 50                  <1> 	push	eax
  2581 00002EA7 A1[4B6F0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2582 00002EAC E837000000          <1> 	call 	get_pde
  2583                              <1> 		; EDX = PDE address
  2584                              <1> 		; EAX = PDE value
  2585 00002EB1 5A                  <1> 	pop	edx ; physical page address
  2586 00002EB2 722A                <1> 	jc	short spte_err ; PDE not present
  2587                              <1> 	;
  2588 00002EB4 53                  <1> 	push	ebx ; 24/07/2015
  2589 00002EB5 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2590                              <1> 			    ; EDX = PT address (physical)	
  2591 00002EB9 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2592 00002EBC 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2593                              <1> 			 ; clear higher 10 bits (PD bits)
  2594 00002EC2 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2595 00002EC5 01C3                <1> 	add	ebx, eax
  2596                              <1> 	;
  2597 00002EC7 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2598 00002EC9 A801                <1> 	test	al, 1
  2599 00002ECB 740C                <1> 	jz	short spte_0
  2600 00002ECD 09D2                <1> 	or	edx, edx
  2601 00002ECF 750F                <1> 	jnz	short spte_1
  2602 00002ED1 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2603 00002ED5 89C2                <1> 	mov	edx, eax
  2604 00002ED7 EB09                <1> 	jmp	short spte_2	
  2605                              <1> spte_0:
  2606                              <1> 	; If this PTE contains a swap (disk) address,
  2607                              <1> 	; it can be updated by using 'swap_in' procedure
  2608                              <1> 	; only!
  2609 00002ED9 21C0                <1> 	and	eax, eax
  2610 00002EDB 7403                <1> 	jz	short spte_1
  2611                              <1> 	; 24/07/2015
  2612                              <1> 	; swapped page ! (on disk)
  2613 00002EDD 5B                  <1> 	pop	ebx
  2614                              <1> spte_err:
  2615 00002EDE F9                  <1> 	stc
  2616 00002EDF C3                  <1> 	retn
  2617                              <1> spte_1: 
  2618 00002EE0 89D0                <1> 	mov	eax, edx
  2619                              <1> spte_2:
  2620 00002EE2 09CA                <1> 	or	edx, ecx
  2621                              <1> 	; 23/06/2015
  2622 00002EE4 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2623                              <1> 	; 24/07/2015
  2624 00002EE6 5B                  <1> 	pop	ebx
  2625 00002EE7 C3                  <1> 	retn
  2626                              <1> 
  2627                              <1> get_pde:	; Get present value of the relevant PDE
  2628                              <1> 	; 20/07/2015
  2629                              <1> 	; 18/04/2015
  2630                              <1> 	; 12/04/2015
  2631                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2632                              <1> 	;
  2633                              <1> 	; INPUT ->
  2634                              <1> 	;	EBX = virtual (linear) address
  2635                              <1> 	;	EAX = page directory (physical) address
  2636                              <1> 	; OUTPUT ->
  2637                              <1> 	;	EDX = Page directory entry address
  2638                              <1> 	;	EAX = Page directory entry value
  2639                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2640                              <1> 	; Modified Registers -> EDX, EAX
  2641                              <1> 	;
  2642 00002EE8 89DA                <1> 	mov	edx, ebx
  2643 00002EEA C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2644 00002EED C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2645 00002EF0 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2646 00002EF2 8B02                <1> 	mov	eax, [edx]
  2647 00002EF4 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2648 00002EF6 751F                <1> 	jnz	short gpte_retn
  2649 00002EF8 F9                  <1> 	stc
  2650                              <1> gpde_retn:	
  2651 00002EF9 C3                  <1> 	retn
  2652                              <1> 
  2653                              <1> get_pte:
  2654                              <1> 		; Get present value of the relevant PTE
  2655                              <1> 	; 29/07/2015
  2656                              <1> 	; 20/07/2015
  2657                              <1> 	; 18/04/2015
  2658                              <1> 	; 12/04/2015
  2659                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2660                              <1> 	;
  2661                              <1> 	; INPUT ->
  2662                              <1> 	;	EBX = virtual (linear) address
  2663                              <1> 	;	EAX = page directory (physical) address
  2664                              <1> 	; OUTPUT ->
  2665                              <1> 	;	EDX = Page table entry address (if CF=0)
  2666                              <1> 	;	      Page directory entry address (if CF=1)
  2667                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2668                              <1> 	;	EAX = Page table entry value (page address)
  2669                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2670                              <1> 	; Modified Registers -> EAX, EDX
  2671                              <1> 	;
  2672 00002EFA E8E9FFFFFF          <1> 	call 	get_pde
  2673 00002EFF 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2674                              <1> 	;jnc	short gpte_1
  2675                              <1> 	;retn
  2676                              <1> ;gpte_1:
  2677 00002F01 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2678 00002F05 89DA                <1> 	mov	edx, ebx
  2679 00002F07 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2680 00002F0A 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2681                              <1> 			 ; clear higher 10 bits (PD bits)
  2682 00002F10 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2683 00002F13 01C2                <1> 	add	edx, eax
  2684 00002F15 8B02                <1> 	mov	eax, [edx]
  2685                              <1> gpte_retn:
  2686 00002F17 C3                  <1> 	retn
  2687                              <1> 
  2688                              <1> deallocate_page_dir:
  2689                              <1> 	; 15/09/2015
  2690                              <1> 	; 05/08/2015
  2691                              <1> 	; 30/04/2015
  2692                              <1> 	; 28/04/2015
  2693                              <1> 	; 17/10/2014
  2694                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2695                              <1> 	;
  2696                              <1> 	; INPUT ->
  2697                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2698                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2699                              <1> 	; OUTPUT ->
  2700                              <1> 	;	All of page tables in the page directory
  2701                              <1> 	;	and page dir's itself will be deallocated
  2702                              <1> 	;	except 'read only' duplicated pages (will be converted
  2703                              <1> 	;	to writable pages).
  2704                              <1> 	;
  2705                              <1> 	; Modified Registers -> EAX
  2706                              <1> 	;
  2707                              <1> 	;
  2708 00002F18 56                  <1> 	push	esi
  2709 00002F19 51                  <1> 	push	ecx
  2710 00002F1A 50                  <1> 	push	eax
  2711 00002F1B 89C6                <1> 	mov	esi, eax 
  2712 00002F1D 31C9                <1> 	xor	ecx, ecx
  2713                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2714                              <1> 	; it must not be deallocated
  2715 00002F1F 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2716                              <1> dapd_0:
  2717 00002F21 AD                  <1> 	lodsd
  2718 00002F22 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2719 00002F24 7409                <1> 	jz	short dapd_1	
  2720 00002F26 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2721 00002F2A E812000000          <1> 	call	deallocate_page_table			
  2722                              <1> dapd_1:
  2723 00002F2F 41                  <1> 	inc	ecx ; page directory entry index
  2724 00002F30 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2725 00002F36 72E9                <1> 	jb	short dapd_0
  2726                              <1> dapd_2:
  2727 00002F38 58                  <1> 	pop	eax
  2728 00002F39 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2729 00002F3E 59                  <1> 	pop	ecx
  2730 00002F3F 5E                  <1> 	pop	esi
  2731 00002F40 C3                  <1> 	retn
  2732                              <1> 
  2733                              <1> deallocate_page_table:
  2734                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2735                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2736                              <1> 	; 19/09/2015
  2737                              <1> 	; 15/09/2015
  2738                              <1> 	; 05/08/2015
  2739                              <1> 	; 30/04/2015
  2740                              <1> 	; 28/04/2015
  2741                              <1> 	; 24/10/2014
  2742                              <1> 	; 23/10/2014
  2743                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2744                              <1> 	;
  2745                              <1> 	; INPUT ->
  2746                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2747                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2748                              <1> 	;	(ECX = page directory entry index)
  2749                              <1> 	; OUTPUT ->
  2750                              <1> 	;	All of pages in the page table and page table's itself
  2751                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2752                              <1> 	;	(will be converted to writable pages).
  2753                              <1> 	;
  2754                              <1> 	; Modified Registers -> EAX
  2755                              <1> 	;
  2756 00002F41 56                  <1> 	push	esi
  2757 00002F42 57                  <1> 	push	edi
  2758 00002F43 52                  <1> 	push	edx
  2759 00002F44 50                  <1> 	push	eax ; *
  2760 00002F45 89C6                <1> 	mov	esi, eax 
  2761 00002F47 31FF                <1> 	xor	edi, edi ; 0
  2762                              <1> dapt_0:
  2763 00002F49 AD                  <1> 	lodsd
  2764 00002F4A A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2765 00002F4C 7455                <1> 	jz	short dapt_1
  2766                              <1> 	;
  2767 00002F4E A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2768                              <1> 				  ; (must be 1)
  2769 00002F50 753F                <1> 	jnz	short dapt_3
  2770                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2771 00002F52 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2772                              <1> 				   ; as child's page ?
  2773 00002F56 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2774                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2775                              <1> 	; ECX = page directory entry index (0-1023)
  2776 00002F58 53                  <1> 	push	ebx
  2777 00002F59 51                  <1> 	push	ecx
  2778 00002F5A 66C1E102            <1> 	shl	cx, 2 ; *4 
  2779 00002F5E 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2780 00002F60 8B0B                <1> 	mov	ecx, [ebx]
  2781 00002F62 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2782 00002F65 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2783 00002F67 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2784                              <1> 	; EDI = page table entry index (0-1023)
  2785 00002F6C 89FA                <1> 	mov	edx, edi 
  2786 00002F6E 66C1E202            <1> 	shl	dx, 2 ; *4 
  2787 00002F72 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2788 00002F74 8B1A                <1> 	mov	ebx, [edx]
  2789 00002F76 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2790 00002F79 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2791 00002F7B 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2792 00002F7F 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2793 00002F84 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2794 00002F86 7507                <1> 	jne	short dapt_2	; not same page
  2795                              <1> 				; deallocate the child's page
  2796 00002F88 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2797 00002F8B 59                  <1> 	pop	ecx
  2798 00002F8C 5B                  <1> 	pop	ebx
  2799 00002F8D EB0D                <1> 	jmp	short dapt_4
  2800                              <1> 
  2801                              <1> ; 24/12/2021
  2802                              <1> ; ('dapt_1' is disabled)
  2803                              <1> ;
  2804                              <1> ;dapt_1:
  2805                              <1> ;	or	eax, eax	; swapped page ?
  2806                              <1> ;	jz	short dapt_5	; no
  2807                              <1> ;				; yes
  2808                              <1> ;	shr	eax, 1
  2809                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2810                              <1> ;				  ; on the swap disk (or in file)
  2811                              <1> ;	jmp	short dapt_5
  2812                              <1> dapt_2:
  2813 00002F8F 59                  <1> 	pop	ecx
  2814 00002F90 5B                  <1> 	pop	ebx
  2815                              <1> dapt_3:	
  2816                              <1> 	; 12/07/2016
  2817 00002F91 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2818 00002F95 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2819                              <1> 	;
  2820                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2821 00002F97 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2822                              <1> dapt_4:
  2823 00002F9C C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2824                              <1> dapt_1:	; 24/12/2021
  2825                              <1> dapt_5:
  2826 00002FA3 47                  <1> 	inc	edi ; page table entry index
  2827 00002FA4 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2828 00002FAA 729D                <1> 	jb	short dapt_0
  2829                              <1> 	;
  2830 00002FAC 58                  <1> 	pop	eax ; *
  2831 00002FAD 5A                  <1> 	pop	edx
  2832 00002FAE 5F                  <1> 	pop	edi	
  2833 00002FAF 5E                  <1> 	pop	esi
  2834                              <1> 	;
  2835                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2836                              <1> 	;retn
  2837                              <1> 
  2838                              <1> deallocate_page:
  2839                              <1> 	; 15/09/2015
  2840                              <1> 	; 28/04/2015
  2841                              <1> 	; 10/03/2015
  2842                              <1> 	; 17/10/2014
  2843                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2844                              <1> 	;
  2845                              <1> 	; INPUT -> 
  2846                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2847                              <1> 	; OUTPUT ->
  2848                              <1> 	;	[free_pages] is increased
  2849                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2850                              <1> 	;	CF = 1 if the page is already deallocated
  2851                              <1> 	; 	       (or not allocated) before.  
  2852                              <1> 	;
  2853                              <1> 	; Modified Registers -> EAX
  2854                              <1> 	;
  2855 00002FB0 53                  <1> 	push	ebx
  2856 00002FB1 52                  <1> 	push	edx
  2857                              <1> 	;
  2858 00002FB2 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2859                              <1> 				     ; 12 bits right
  2860                              <1> 				     ; to get page number
  2861 00002FB5 89C2                <1> 	mov	edx, eax
  2862                              <1> 	; 15/09/2015
  2863 00002FB7 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2864                              <1> 				     ; (1 allocation bit = 1 page)
  2865                              <1> 				     ; (1 allocation bytes = 8 pages)
  2866 00002FBA 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2867                              <1> 				     ; (to get 32 bit position)			
  2868                              <1> 	;
  2869 00002FBD BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2870 00002FC2 01D3                <1> 	add	ebx, edx
  2871 00002FC4 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2872                              <1> 				     ; (allocation bit position)	 
  2873 00002FC7 3B15[546B0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2874                              <1> 				     ; than the address in 'next_page' ?
  2875                              <1> 				     ; (next/first free page value)		
  2876 00002FCD 7306                <1> 	jnb	short dap_1	     ; no	
  2877 00002FCF 8915[546B0000]      <1> 	mov	[next_page], edx     ; yes
  2878                              <1> dap_1:
  2879 00002FD5 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2880                              <1> 				     ; set relevant bit to 1.
  2881                              <1> 				     ; set CF to the previous bit value	
  2882                              <1> 	;cmc			     ; complement carry flag	
  2883                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2884                              <1> 				     ; if the page is already deallocated
  2885                              <1> 				     ; before.	
  2886 00002FD8 FF05[506B0000]      <1>         inc     dword [free_pages]
  2887                              <1> dap_2:
  2888 00002FDE 5A                  <1> 	pop	edx
  2889 00002FDF 5B                  <1> 	pop	ebx
  2890 00002FE0 C3                  <1> 	retn
  2891                              <1> 
  2892                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2893                              <1> ;;                                                              ;;
  2894                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2895                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2896                              <1> ;;                                                              ;;
  2897                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2898                              <1> 
  2899                              <1> ;;$Revision: 5057 $
  2900                              <1> 
  2901                              <1> 
  2902                              <1> ;;align 4
  2903                              <1> ;;proc alloc_page
  2904                              <1> 
  2905                              <1> ;;        pushfd
  2906                              <1> ;;        cli
  2907                              <1> ;;        push    ebx
  2908                              <1> ;;;//-
  2909                              <1> ;;        cmp     [pg_data.pages_free], 1
  2910                              <1> ;;        jle     .out_of_memory
  2911                              <1> ;;;//-
  2912                              <1> ;;
  2913                              <1> ;;        mov     ebx, [page_start]
  2914                              <1> ;;        mov     ecx, [page_end]
  2915                              <1> ;;.l1:
  2916                              <1> ;;        bsf     eax, [ebx];
  2917                              <1> ;;        jnz     .found
  2918                              <1> ;;        add     ebx, 4
  2919                              <1> ;;        cmp     ebx, ecx
  2920                              <1> ;;        jb      .l1
  2921                              <1> ;;        pop     ebx
  2922                              <1> ;;        popfd
  2923                              <1> ;;        xor     eax, eax
  2924                              <1> ;;        ret
  2925                              <1> ;;.found:
  2926                              <1> ;;;//-
  2927                              <1> ;;        dec     [pg_data.pages_free]
  2928                              <1> ;;        jz      .out_of_memory
  2929                              <1> ;;;//-
  2930                              <1> ;;        btr     [ebx], eax
  2931                              <1> ;;        mov     [page_start], ebx
  2932                              <1> ;;        sub     ebx, sys_pgmap
  2933                              <1> ;;        lea     eax, [eax+ebx*8]
  2934                              <1> ;;        shl     eax, 12
  2935                              <1> ;;;//-       dec [pg_data.pages_free]
  2936                              <1> ;;        pop     ebx
  2937                              <1> ;;        popfd
  2938                              <1> ;;        ret
  2939                              <1> ;;;//-
  2940                              <1> ;;.out_of_memory:
  2941                              <1> ;;        mov     [pg_data.pages_free], 1
  2942                              <1> ;;        xor     eax, eax
  2943                              <1> ;;        pop     ebx
  2944                              <1> ;;        popfd
  2945                              <1> ;;        ret
  2946                              <1> ;;;//-
  2947                              <1> ;;endp
  2948                              <1> 
  2949                              <1> duplicate_page_dir:
  2950                              <1> 	; 21/09/2015
  2951                              <1> 	; 31/08/2015
  2952                              <1> 	; 20/07/2015
  2953                              <1> 	; 28/04/2015
  2954                              <1> 	; 27/04/2015
  2955                              <1> 	; 18/04/2015
  2956                              <1> 	; 12/04/2015
  2957                              <1> 	; 18/10/2014
  2958                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  2959                              <1> 	;
  2960                              <1> 	; INPUT -> 
  2961                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  2962                              <1> 	;		    page directory.
  2963                              <1> 	; OUTPUT ->
  2964                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  2965                              <1> 	;	       page directory.
  2966                              <1> 	;	(New page directory with new page table entries.)
  2967                              <1> 	;	(New page tables with read only copies of the parent's
  2968                              <1> 	;	pages.)
  2969                              <1> 	;	EAX = 0 -> Error (CF = 1)
  2970                              <1> 	;
  2971                              <1> 	; Modified Registers -> none (except EAX)
  2972                              <1> 	;
  2973 00002FE1 E802FEFFFF          <1> 	call	allocate_page
  2974 00002FE6 723E                <1> 	jc	short dpd_err
  2975                              <1> 	;
  2976 00002FE8 55                  <1> 	push	ebp ; 20/07/2015
  2977 00002FE9 56                  <1> 	push	esi
  2978 00002FEA 57                  <1> 	push	edi
  2979 00002FEB 53                  <1> 	push	ebx
  2980 00002FEC 51                  <1> 	push	ecx
  2981 00002FED 8B35[4B6F0000]      <1> 	mov	esi, [u.pgdir]
  2982 00002FF3 89C7                <1> 	mov	edi, eax
  2983 00002FF5 50                  <1> 	push	eax ; save child's page directory address
  2984                              <1> 	; 31/08/2015
  2985                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  2986                              <1> 	; (use same system space for all user page tables) 
  2987 00002FF6 A5                  <1> 	movsd
  2988 00002FF7 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  2989 00002FFC B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  2990                              <1> dpd_0:	
  2991 00003001 AD                  <1> 	lodsd
  2992                              <1> 	;or	eax, eax
  2993                              <1>         ;jnz     short dpd_1
  2994 00003002 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  2995 00003004 7508                <1> 	jnz	short dpd_1
  2996                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  2997 00003006 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  2998 0000300C EB0F                <1> 	jmp	short dpd_2
  2999                              <1> dpd_1:	
  3000 0000300E 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3001 00003012 89C3                <1> 	mov	ebx, eax
  3002                              <1> 	; EBX = Parent's page table address
  3003 00003014 E81F000000          <1> 	call	duplicate_page_table
  3004 00003019 720C                <1> 	jc	short dpd_p_err
  3005                              <1> 	; EAX = Child's page table address
  3006 0000301B 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3007                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3008                              <1> 			 ; (present, writable, user)
  3009                              <1> dpd_2:
  3010 0000301D AB                  <1> 	stosd
  3011 0000301E E2E1                <1> 	loop	dpd_0
  3012                              <1> 	;
  3013 00003020 58                  <1> 	pop	eax  ; restore child's page directory address
  3014                              <1> dpd_3:
  3015 00003021 59                  <1> 	pop	ecx
  3016 00003022 5B                  <1> 	pop	ebx
  3017 00003023 5F                  <1> 	pop	edi
  3018 00003024 5E                  <1> 	pop	esi
  3019 00003025 5D                  <1> 	pop	ebp ; 20/07/2015
  3020                              <1> dpd_err:
  3021 00003026 C3                  <1> 	retn
  3022                              <1> dpd_p_err:
  3023                              <1> 	; release the allocated pages missing (recover free space)
  3024 00003027 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3025 00003028 8B1D[4B6F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3026 0000302E E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3027 00003033 29C0                <1> 	sub	eax, eax ; 0
  3028 00003035 F9                  <1> 	stc
  3029 00003036 EBE9                <1> 	jmp	short dpd_3	
  3030                              <1> 
  3031                              <1> duplicate_page_table:
  3032                              <1> 	; 31/12/2021
  3033                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3034                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3035                              <1> 	; 21/09/2015
  3036                              <1> 	; 20/07/2015
  3037                              <1> 	; 05/05/2015
  3038                              <1> 	; 28/04/2015
  3039                              <1> 	; 27/04/2015
  3040                              <1> 	; 18/04/2015
  3041                              <1> 	; 18/10/2014
  3042                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3043                              <1> 	;
  3044                              <1> 	; INPUT -> 
  3045                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3046                              <1> 	;       20/02/2017		 
  3047                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3048                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3049                              <1> 	; OUTPUT ->
  3050                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3051                              <1> 	;	      (with 'read only' attribute of page table entries)
  3052                              <1> 	;	20/02/2017
  3053                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3054                              <1> 	;	
  3055                              <1> 	;	CF = 1 -> error 
  3056                              <1> 	;
  3057                              <1> 	; Modified Registers -> EBP (except EAX)
  3058                              <1> 	;
  3059 00003038 E8ABFDFFFF          <1> 	call	allocate_page
  3060 0000303D 725B                <1> 	jc	short dpt_err
  3061                              <1> 	;
  3062 0000303F 50                  <1> 	push	eax ; *
  3063 00003040 56                  <1> 	push	esi
  3064 00003041 57                  <1> 	push	edi
  3065 00003042 52                  <1> 	push	edx
  3066 00003043 51                  <1> 	push	ecx
  3067                              <1> 	;
  3068 00003044 89DE                <1> 	mov	esi, ebx
  3069 00003046 89C7                <1> 	mov	edi, eax
  3070 00003048 89C2                <1> 	mov	edx, eax
  3071 0000304A 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3072                              <1> dpt_0:
  3073 00003050 AD                  <1> 	lodsd
  3074 00003051 21C0                <1> 	and	eax, eax
  3075 00003053 7435                <1> 	jz	short dpt_3
  3076 00003055 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3077                              <1> 	; 24/12/2021
  3078 00003057 7503                <1> 	jnz	short dpt_1
  3079                              <1> 	;jz	short dpt_p_err
  3080                              <1> 	; 31/12/2021
  3081 00003059 F9                  <1> 	stc
  3082 0000305A EB39                <1> 	jmp	short dpt_p_err
  3083                              <1> 
  3084                              <1> ; 24/12/2021
  3085                              <1> ; ('reload_page' procedure call is disabled)
  3086                              <1> ;
  3087                              <1> ;	; 20/07/2015
  3088                              <1> ;	; ebp = virtual (linear) address of the memory page
  3089                              <1> ;	call	reload_page ; 28/04/2015
  3090                              <1> ;	jc	short dpt_p_err
  3091                              <1> dpt_1:
  3092                              <1> 	; 21/09/2015
  3093 0000305C 89C1                <1> 	mov	ecx, eax
  3094 0000305E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3095 00003062 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3096 00003065 751A                <1> 	jnz	short dpt_2
  3097                              <1> 	; Read only (parent) page
  3098                              <1> 	; 	- there is a third process which uses this page -
  3099                              <1> 	; Allocate a new page for the child process
  3100 00003067 E87CFDFFFF          <1> 	call	allocate_page
  3101 0000306C 7227                <1> 	jc	short dpt_p_err
  3102 0000306E 57                  <1> 	push	edi
  3103 0000306F 56                  <1> 	push	esi
  3104 00003070 89CE                <1> 	mov	esi, ecx
  3105 00003072 89C7                <1> 	mov	edi, eax
  3106 00003074 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3107 00003079 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3108 0000307B 5E                  <1> 	pop	esi
  3109 0000307C 5F                  <1> 	pop	edi
  3110                              <1> 	;
  3111                              <1> 
  3112                              <1> ; 24/12/2021
  3113                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3114                              <1> ; 
  3115                              <1> ;	push	ebx
  3116                              <1> ;	push	eax
  3117                              <1> ;	; 20/07/2015
  3118                              <1> ;	mov	ebx, ebp
  3119                              <1> ;	; ebx = virtual (linear) address of the memory page
  3120                              <1> ;	call	add_to_swap_queue
  3121                              <1> ;	pop	eax
  3122                              <1> ;	pop	ebx
  3123                              <1> 
  3124                              <1> 	; 21/09/2015
  3125 0000307D 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3126                              <1> 		; user + writable + present page
  3127 0000307F EB09                <1> 	jmp	short dpt_3
  3128                              <1> dpt_2:
  3129                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3130 00003081 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3131                              <1> 		    ; (read only page!)
  3132 00003083 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3133 00003086 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3134                              <1> dpt_3:
  3135 0000308A AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3136                              <1> 	;
  3137 0000308B 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3138                              <1> 	;
  3139 00003091 39D7                <1> 	cmp	edi, edx
  3140 00003093 72BB                <1> 	jb	short dpt_0
  3141                              <1> dpt_p_err:
  3142 00003095 59                  <1> 	pop	ecx
  3143 00003096 5A                  <1> 	pop	edx
  3144 00003097 5F                  <1> 	pop	edi
  3145 00003098 5E                  <1> 	pop	esi
  3146 00003099 58                  <1> 	pop	eax ; *
  3147                              <1> dpt_err:
  3148 0000309A C3                  <1> 	retn
  3149                              <1> 
  3150                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3151                              <1> 	; 31/12/2021
  3152                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3153                              <1> 	; 21/09/2015
  3154                              <1> 	; 19/09/2015
  3155                              <1> 	; 17/09/2015
  3156                              <1> 	; 28/08/2015
  3157                              <1> 	; 20/07/2015
  3158                              <1> 	; 28/06/2015
  3159                              <1> 	; 03/05/2015
  3160                              <1> 	; 30/04/2015
  3161                              <1> 	; 18/04/2015
  3162                              <1> 	; 12/04/2015
  3163                              <1> 	; 30/10/2014
  3164                              <1> 	; 11/09/2014
  3165                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3166                              <1> 	;
  3167                              <1> 	; Note: This is not an interrupt/exception handler.
  3168                              <1> 	;	This is a 'page fault remedy' subroutine 
  3169                              <1> 	;	which will be called by standard/uniform
  3170                              <1> 	;	exception handler.
  3171                              <1> 	;
  3172                              <1> 	; INPUT -> 
  3173                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3174                              <1> 	;
  3175                              <1> 	;	cr2 = the virtual (linear) address 
  3176                              <1> 	;	      which has caused to page fault (19/09/2015)
  3177                              <1> 	;
  3178                              <1> 	; OUTPUT ->
  3179                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3180                              <1> 	;	EAX = 0 -> no error
  3181                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3182                              <1> 	;
  3183                              <1> 	; Modified Registers -> none (except EAX)
  3184                              <1> 	;	
  3185                              <1>         ;
  3186                              <1>         ; ERROR CODE:
  3187                              <1> 	;	 31  .....	4   3	2   1	0
  3188                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3189                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3190                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3191                              <1> 	;
  3192                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3193                              <1>     	;		a page-protection violation. When not set,
  3194                              <1> 	;		it was caused by a non-present page.
  3195                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3196                              <1> 	;		a page write. When not set, it was caused
  3197                              <1> 	;		by a page read.
  3198                              <1> 	; U : USER    -	When set, the page fault was caused 
  3199                              <1> 	;		while CPL = 3. 
  3200                              <1> 	;		This does not necessarily mean that
  3201                              <1> 	;		the page fault was a privilege violation.
  3202                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3203                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3204                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3205                              <1> 	;     FETCH	an instruction fetch
  3206                              <1> 	;
  3207                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3208                              <1> 	;  31               22                  12 11                    0
  3209                              <1> 	; +-------------------+-------------------+-----------------------+
  3210                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3211                              <1>        	; +-------------------+-------------------+-----------------------+
  3212                              <1> 	;
  3213                              <1> 
  3214                              <1> 	;; CR3 REGISTER (Control Register 3)
  3215                              <1> 	;  31                                   12             5 4 3 2   0
  3216                              <1> 	; +---------------------------------------+-------------+---+-----+
  3217                              <1>       	; |                                       |  		|P|P|     |
  3218                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3219                              <1>       	; |                                       | 		|D|T|     |
  3220                              <1>    	; +---------------------------------------+-------------+---+-----+
  3221                              <1> 	;
  3222                              <1> 	;	PWT    - WRITE THROUGH
  3223                              <1> 	;	PCD    - CACHE DISABLE		
  3224                              <1> 	;
  3225                              <1> 	;
  3226                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3227                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3228                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3229                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3230                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3231                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3232                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3233                              <1> 	;
  3234                              <1>         ;       P      - PRESENT
  3235                              <1>         ;       R/W    - READ/WRITE
  3236                              <1>         ;       U/S    - USER/SUPERVISOR
  3237                              <1> 	;	PWT    - WRITE THROUGH
  3238                              <1> 	;	PCD    - CACHE DISABLE	
  3239                              <1> 	;	A      - ACCESSED	
  3240                              <1>         ;       D      - DIRTY (IGNORED)
  3241                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3242                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3243                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3244                              <1> 	;
  3245                              <1> 	;
  3246                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3247                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3248                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3249                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3250                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3251                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3252                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3253                              <1> 	;
  3254                              <1>         ;       P      - PRESENT
  3255                              <1>         ;       R/W    - READ/WRITE
  3256                              <1>         ;       U/S    - USER/SUPERVISOR
  3257                              <1> 	;	PWT    - WRITE THROUGH
  3258                              <1> 	;	PCD    - CACHE DISABLE	
  3259                              <1> 	;	A      - ACCESSED	
  3260                              <1>         ;       D      - DIRTY
  3261                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3262                              <1> 	;	G      - GLOBAL	 
  3263                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3264                              <1> 	;
  3265                              <1> 	;
  3266                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3267                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3268                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3269                              <1>       	; |                                       |     | | | | | | |U|R| |
  3270                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3271                              <1>       	; |                                       |     | | | | | | |S|W| |
  3272                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3273                              <1> 	;
  3274                              <1>         ;       P      - PRESENT
  3275                              <1>         ;       R/W    - READ/WRITE
  3276                              <1>         ;       U/S    - USER/SUPERVISOR
  3277                              <1>         ;       D      - DIRTY
  3278                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3279                              <1> 	;
  3280                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3281                              <1> 	;
  3282                              <1> 	;
  3283                              <1> 	;; Invalid Page Table Entry
  3284                              <1> 	; 31                                                           1 0
  3285                              <1>       	; +-------------------------------------------------------------+-+
  3286                              <1>       	; |                                                             | |
  3287                              <1>       	; |                          AVAILABLE                          |0|
  3288                              <1>       	; |                                                             | |
  3289                              <1>       	; +-------------------------------------------------------------+-+
  3290                              <1> 	;
  3291                              <1> 
  3292 0000309B 53                  <1> 	push	ebx
  3293 0000309C 52                  <1> 	push	edx
  3294 0000309D 51                  <1> 	push	ecx
  3295                              <1> 	;
  3296                              <1> 	; 21/09/2015 (debugging)
  3297 0000309E FF05[5B6F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3298 000030A4 FF05[C07F0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3299                              <1> 	; 28/06/2015
  3300                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3301 000030AA 8A15[B87F0000]      <1> 	mov	dl, [error_code]
  3302                              <1> 	;
  3303 000030B0 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3304                              <1> 			; sign
  3305 000030B3 7425                <1> 	jz	short pfh_alloc_np
  3306                              <1> 	; 
  3307                              <1> 	; If it is not a 'write on read only page' type page fault
  3308                              <1> 	; major page fault error with minor reason must be returned without 
  3309                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3310                              <1> 	; after return here!
  3311                              <1> 	; Page fault will be remedied, by copying page contents
  3312                              <1> 	; to newly allocated page with write permission;
  3313                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3314                              <1> 	; used for working with minimum possible memory usage. 
  3315                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3316                              <1> 	; process with 'read only' flag. If the child process attempts to
  3317                              <1> 	; write on these read only pages, page fault will be directed here
  3318                              <1> 	; for allocating a new page with same data/content. 
  3319                              <1> 	;
  3320                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3321                              <1> 	; will not force to separate CODE and DATA space 
  3322                              <1> 	; in a process/program... 
  3323                              <1> 	; CODE segment/section may contain DATA!
  3324                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3325                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3326                              <1> 	;	
  3327 000030B5 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3328                              <1> 			; sign
  3329 000030B8 7418                <1>         jz      pfh_p_err
  3330                              <1> 	; 31/08/2015
  3331 000030BA F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3332                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3333 000030BD 7413                <1>         jz	short pfh_pv_err
  3334                              <1> 	;
  3335                              <1> 	; make a new page and copy the parent's page content
  3336                              <1> 	; as the child's new page content
  3337                              <1> 	;
  3338 000030BF 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3339                              <1> 			 ; which has caused to page fault
  3340 000030C2 E87C000000          <1> 	call 	copy_page
  3341 000030C7 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3342                              <1> 	;
  3343 000030C9 EB72                <1>         jmp     pfh_cpp_ok
  3344                              <1> 
  3345                              <1> 	; 31/12/2021 (short jump)
  3346                              <1> pfh_im_err:
  3347 000030CB B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3348                              <1> 			; Major (Primary) Error: Page Fault
  3349                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3350 000030D0 EB6D                <1> 	jmp	short pfh_err_retn
  3351                              <1> 
  3352                              <1> 	; 31/12/2021
  3353                              <1> pfh_p_err: ; 09/03/2015
  3354                              <1> pfh_pv_err:
  3355                              <1> 	; Page fault was caused by a protection-violation
  3356 000030D2 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3357                              <1> 			; Major (Primary) Error: Page Fault
  3358                              <1> 			; Minor (Secondary) Error: Protection violation !
  3359 000030D7 F9                  <1> 	stc
  3360 000030D8 EB65                <1> 	jmp	short pfh_err_retn
  3361                              <1> 	
  3362                              <1> pfh_alloc_np:
  3363 000030DA E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3364 000030DF 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3365                              <1> pfh_chk_cpl:
  3366                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3367                              <1> 		; (Lower 12 bits are ZERO, because 
  3368                              <1> 		;	the address is on a page boundary)
  3369 000030E1 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3370 000030E4 7505                <1> 	jnz	short pfh_um
  3371                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3372 000030E6 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3373                              <1> 			 ; of the current/active page directory
  3374                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3375                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3376 000030E9 EB06                <1> 	jmp	short pfh_get_pde
  3377                              <1> 	;
  3378                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3379 000030EB 8B1D[4B6F0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3380                              <1> 			; Physical address of the USER's page directory
  3381                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3382                              <1> pfh_get_pde:
  3383 000030F1 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3384 000030F4 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3385                              <1> 			 ; which has been caused to page fault
  3386                              <1> 			 ;
  3387 000030F7 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3388 000030FA 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3389                              <1> 	;
  3390 000030FD 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3391 000030FF 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3392 00003101 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3393 00003104 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3394                              <1> 			  	  ; set/validate page directory entry
  3395 00003106 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3396 0000310B 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3397 0000310D 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3398 0000310F EB16                <1> 	jmp	short pfh_get_pte
  3399                              <1> pfh_set_pde:
  3400                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3401                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3402                              <1> 	;
  3403 00003111 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3404 00003113 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3405 00003115 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3406 00003117 89C3                <1> 	mov	ebx, eax
  3407 00003119 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3408 0000311E 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3409                              <1> pfh_spde_1:
  3410                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3411 00003120 89C1                <1> 	mov	ecx, eax
  3412 00003122 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3413                              <1> pfh_get_pte:
  3414 00003127 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3415                              <1> 			 ; which has been caused to page fault
  3416 0000312A 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3417 0000312C C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3418                              <1> 			 ; higher 20 bits of the page fault address 
  3419 0000312F 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3420 00003134 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3421 00003137 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3422                              <1> ; 24/12/2021
  3423                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3424                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3425                              <1> ; 24/12/2021
  3426                              <1> ; ('swap_in' procedure call has been disabled)
  3427                              <1> ;
  3428                              <1> ;	and	eax, eax
  3429                              <1> ;	jz	short pfh_gpte_1
  3430                              <1> ;	; 20/07/2015
  3431                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3432                              <1> ;	push	ebp ; 20/07/2015
  3433                              <1> ;	mov	ebp, cr2
  3434                              <1> ;		; ECX = physical address of the page table entry
  3435                              <1> ;		; EBX = Memory page address (physical!)
  3436                              <1> ;		; EAX = Swap disk (offset) address
  3437                              <1> ;		; EBP = virtual address (page fault address)
  3438                              <1> ;	call	swap_in
  3439                              <1> ;	pop	ebp
  3440                              <1> ;	jc      short pfh_err_retn
  3441                              <1> ;	xchg	ecx, ebx
  3442                              <1> ;		; EBX = physical address of the page table entry
  3443                              <1> ;		; ECX = new page
  3444                              <1> pfh_gpte_1:
  3445 00003139 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3446 0000313B 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3447                              <1> pfh_cpp_ok:
  3448                              <1> ; 24/12/2021
  3449                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3450                              <1> ;
  3451                              <1> ;	; 20/07/2015
  3452                              <1> ;	mov	ebx, cr2
  3453                              <1> ;	call 	add_to_swap_queue
  3454                              <1> 	;
  3455                              <1> 	; The new PTE (which contains the new page) will be added to 
  3456                              <1> 	; the swap queue, here. 
  3457                              <1> 	; (Later, if memory will become insufficient, 
  3458                              <1> 	; one page will be swapped out which is at the head of 
  3459                              <1> 	; the swap queue by using FIFO and access check methods.)
  3460                              <1> 	;
  3461 0000313D 31C0                <1> 	xor	eax, eax  ; 0
  3462                              <1> 	;
  3463                              <1> pfh_err_retn:
  3464 0000313F 59                  <1> 	pop	ecx
  3465 00003140 5A                  <1> 	pop	edx
  3466 00003141 5B                  <1> 	pop	ebx
  3467 00003142 C3                  <1> 	retn 
  3468                              <1> 	
  3469                              <1> copy_page:
  3470                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3471                              <1> 	; 16/04/2021
  3472                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3473                              <1> 	; 22/09/2015
  3474                              <1> 	; 21/09/2015
  3475                              <1> 	; 19/09/2015
  3476                              <1> 	; 07/09/2015
  3477                              <1> 	; 31/08/2015
  3478                              <1> 	; 20/07/2015
  3479                              <1> 	; 05/05/2015
  3480                              <1> 	; 03/05/2015
  3481                              <1> 	; 18/04/2015
  3482                              <1> 	; 12/04/2015
  3483                              <1> 	; 30/10/2014
  3484                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3485                              <1> 	;
  3486                              <1> 	; INPUT -> 
  3487                              <1> 	;	EBX = Virtual (linear) address of source page
  3488                              <1> 	;	     (Page fault address)
  3489                              <1> 	; OUTPUT ->
  3490                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3491                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3492                              <1> 	;	EAX = 0 (CF = 1) 
  3493                              <1> 	;		if there is not a free page to be allocated
  3494                              <1> 	;	(page content of the source page will be copied
  3495                              <1> 	;	onto the target/new page) 	
  3496                              <1> 	;
  3497                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3498                              <1> 	;
  3499                              <1> 
  3500                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3501                              <1> 	; INPUT: 
  3502                              <1> 	;	EBX = Virtual (linear) address of source page
  3503                              <1> 	;	     (Page fault address)
  3504                              <1> 	; OUTPUT:
  3505                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3506                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3507                              <1> 	;	EAX = 0 (CF = 1) 
  3508                              <1> 	;		if there is not a free page to be allocated
  3509                              <1> 	;	(page content of the source page will be copied
  3510                              <1> 	;	onto the target/new page) 	
  3511                              <1> 	;
  3512                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3513                              <1> 	
  3514 00003143 56                  <1> 	push	esi ; *
  3515 00003144 57                  <1> 	push	edi ; **
  3516                              <1> 	; 16/04/2021
  3517                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3518                              <1> 	;push	ebx ; ***
  3519                              <1> 	;push	ecx ; ****
  3520 00003145 31F6                <1> 	xor 	esi, esi
  3521 00003147 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3522 0000314A 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3523 0000314C C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3524 0000314F 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3525 00003152 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3526 00003154 031D[4B6F0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3527 0000315A 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3528 0000315C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3529 00003160 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3530 00003162 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3531 00003168 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3532 0000316C 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3533                              <1> 	; 07/09/2015
  3534 0000316E 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3535                              <1> 				     ; read only page as a child process?)	
  3536 00003173 7509                <1> 	jnz	short cpp_0 ; yes
  3537 00003175 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3538 00003177 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3539 0000317C EB32                <1> 	jmp	short cpp_1
  3540                              <1> cpp_0:
  3541 0000317E 89FE                <1> 	mov	esi, edi
  3542 00003180 0335[4F6F0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3543 00003186 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3544 00003188 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3545 0000318C 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3546 0000318E 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3547 00003194 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3548 00003198 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3549 0000319A 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3550                              <1> 	; 21/09/2015
  3551 0000319C 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3552 0000319E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3553                              <1> 	;
  3554 000031A2 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3555 000031A5 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3556                              <1> 	;
  3557 000031A7 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3558 000031AC 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3559 000031AE 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3560                              <1> 			    ; Convert child's page to writable page
  3561                              <1> cpp_1:
  3562 000031B0 E833FCFFFF          <1> 	call	allocate_page
  3563 000031B5 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3564 000031B7 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3565 000031B9 7405                <1> 	jz	short cpp_2
  3566                              <1> 		; Convert read only page to writable page 
  3567                              <1> 		;(for the parent of the current process)
  3568                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3569                              <1> 	; 22/09/2015
  3570 000031BB 890E                <1> 	mov	[esi], ecx
  3571 000031BD 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3572                              <1> 				 ; 1+2+4 = 7
  3573                              <1> cpp_2:
  3574 000031C0 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3575                              <1> 	; 07/09/2015
  3576 000031C2 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3577 000031C4 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3578 000031C9 F3A5                <1> 	rep	movsd ; 31/08/2015
  3579                              <1> cpp_3:		
  3580 000031CB 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3581 000031CD 8903                <1> 	mov	[ebx], eax ; Update PTE
  3582 000031CF 28C0                <1> 	sub	al, al ; clear attributes
  3583                              <1> cpp_4:
  3584                              <1> 	; 16/04/2021
  3585                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3586                              <1> 	;pop	ecx ; ****
  3587                              <1> 	;pop	ebx ; ***
  3588 000031D1 5F                  <1> 	pop	edi ; **
  3589 000031D2 5E                  <1> 	pop	esi ; *
  3590 000031D3 C3                  <1> 	retn
  3591                              <1> 
  3592                              <1> ;; 28/04/2015
  3593                              <1> ;; 24/10/2014
  3594                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3595                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3596                              <1> ;;
  3597                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3598                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3599                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3600                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3601                              <1> ;;
  3602                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3603                              <1> ;;
  3604                              <1> ;; Method:
  3605                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3606                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3607                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3608                              <1> ;;	When a new page is being allocated, swap queue is updated
  3609                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3610                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3611                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3612                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3613                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3614                              <1> ;;	offset value becomes it's previous offset value - 4.
  3615                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3616                              <1> ;;	the queue/list is not shifted.
  3617                              <1> ;;	After the queue/list shift, newly allocated page is added
  3618                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3619                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3620                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3621                              <1> ;;	
  3622                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3623                              <1> ;;	the first non-accessed, writable page in the list, 
  3624                              <1> ;;	from the head to the tail. The list is shifted to left 
  3625                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3626                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3627                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3628                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3629                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3630                              <1> ;;	procedure will be failed)...
  3631                              <1> ;;
  3632                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3633                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3634                              <1> ;;	(PTE) will be added to the tail of the queue after
  3635                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3636                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3637                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3638                              <1> ;;
  3639                              <1> ;;
  3640                              <1> ;;	
  3641                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3642                              <1> ;;
  3643                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3644                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3645                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3646                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3647                              <1> ;;
  3648                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3649                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3650                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3651                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3652                              <1> ;; 		 (entire swap space must be accessed by using
  3653                              <1> ;;		 31 bit offset address) 
  3654                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3655                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3656                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3657                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3658                              <1> ;;
  3659                              <1> ;; 					
  3660                              <1> ;; Method:
  3661                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3662                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3663                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3664                              <1> ;;	Swapping out is performed by using swap page queue.
  3665                              <1> ;;
  3666                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3667                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3668                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3669                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3670                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3671                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3672                              <1> ;;	calculated by adding offset value to the swap partition's 
  3673                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3674                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3675                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3676                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3677                              <1> ;;	is in a partitioned virtual hard disk.) 
  3678                              <1> ;;
  3679                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3680                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3681                              <1> ;;
  3682                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3683                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3684                              <1> ;;
  3685                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3686                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3687                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3688                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3689                              <1> ;;	it means relevant (respective) block is in use, and, 
  3690                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3691                              <1> ;;      swap disk/file block is free.
  3692                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3693                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3694                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3695                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3696                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3697                              <1> ;;	------------------------------------------------------------
  3698                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3699                              <1> ;;	------------------------------------------------------------
  3700                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3701                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3702                              <1> ;;
  3703                              <1> ;;	..............................................................
  3704                              <1> ;;
  3705                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3706                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3707                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3708                              <1> ;;	position with value of 1 on the table is converted to swap
  3709                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3710                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3711                              <1> ;;	number of physical swap disk or virtual swap disk)
  3712                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3713                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3714                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3715                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3716                              <1> ;;	If disk write procedure returns with error or free count of 
  3717                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3718                              <1> ;;	'insufficient memory error' (cf=1). 
  3719                              <1> ;;
  3720                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3721                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3722                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3723                              <1> ;;	free blocks after a disk write error. It will return to 
  3724                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3725                              <1> ;;
  3726                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3727                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3728                              <1> ;;	address (cf=0). 
  3729                              <1> ;;
  3730                              <1> ;;	..............................................................
  3731                              <1> ;;
  3732                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3733                              <1> ;;	file sectors at specified memory page. Then page allocation
  3734                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3735                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3736                              <1> ;;	to do, except to terminate the process which is the owner of
  3737                              <1> ;;	the swapped page.
  3738                              <1> ;;
  3739                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3740                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3741                              <1> ;;	updates [swpd_first] pointer if it is required.
  3742                              <1> ;;
  3743                              <1> ;;	..............................................................	 
  3744                              <1> ;;
  3745                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3746                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3747                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3748                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3749                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3750                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3751                              <1> ;;
  3752                              <1> 
  3753                              <1> ; 24/12/2021
  3754                              <1> ; ('swap_in' procedure call is disabled)
  3755                              <1> 
  3756                              <1> ;swap_in:
  3757                              <1> 	; 31/08/2015
  3758                              <1> 	; 20/07/2015
  3759                              <1> 	; 28/04/2015
  3760                              <1> 	; 18/04/2015
  3761                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3762                              <1> 	;
  3763                              <1> 	; INPUT -> 
  3764                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3765                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3766                              <1> 	;	EAX = Offset Address for the swapped page on the
  3767                              <1> 	;	      swap disk or in the swap file.
  3768                              <1> 	;
  3769                              <1> 	; OUTPUT ->
  3770                              <1> 	;	EAX = 0 if loading at memory has been successful
  3771                              <1> 	;
  3772                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3773                              <1> 	;		  or sector not present or drive not ready
  3774                              <1> 	;	     EAX = Error code
  3775                              <1> 	;	     [u.error] = EAX 
  3776                              <1> 	;		       = The last error code for the process
  3777                              <1> 	;		         (will be reset after returning to user)	  
  3778                              <1> 	;
  3779                              <1> 	; Modified Registers -> EAX
  3780                              <1> 	;
  3781                              <1> 
  3782                              <1> ;       cmp     dword [swp_drv], 0
  3783                              <1> ;	jna	short swpin_dnp_err
  3784                              <1> ;
  3785                              <1> ;	cmp	eax, [swpd_size]
  3786                              <1> ;	jnb	short swpin_snp_err
  3787                              <1> ;
  3788                              <1> ;	push	esi
  3789                              <1> ;	push	ebx
  3790                              <1> ;	push	ecx
  3791                              <1> ;	mov	esi, [swp_drv]	
  3792                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3793                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3794                              <1> ;		; size different than 512 bytes, logical disk sector
  3795                              <1> ;		; size is 512 bytes and disk reading procedure
  3796                              <1> ;		; will be performed for reading 4096 bytes
  3797                              <1> ;		; (2*2048, 8*512). 
  3798                              <1> ;	; ESI = Logical disk description table address
  3799                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3800                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3801                              <1> ;	; ECX = Sector count ; 8 sectors
  3802                              <1> ;	push	eax
  3803                              <1> ;	call	logical_disk_read
  3804                              <1> ;	pop	eax
  3805                              <1> ;	jnc	short swpin_read_ok
  3806                              <1> ;	;
  3807                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3808                              <1> ;	mov	[u.error], eax
  3809                              <1> ;	jmp	short swpin_retn
  3810                              <1> ;	;
  3811                              <1> ;swpin_read_ok:
  3812                              <1> ;	; EAX = Offset address (logical sector number)
  3813                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3814                              <1> ;	;
  3815                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3816                              <1> ;	; 20/07/2015
  3817                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3818                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3819                              <1> ;	mov	bl, [u.uno] ; current process number
  3820                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3821                              <1> ;	call	swap_queue_shift
  3822                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3823                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3824                              <1> ;	; zf = 1
  3825                              <1> ;swpin_retn:
  3826                              <1> ;	pop	ecx
  3827                              <1> ;	pop	ebx
  3828                              <1> ;	pop	esi
  3829                              <1> ;	retn
  3830                              <1> ;
  3831                              <1> ;swpin_dnp_err:
  3832                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3833                              <1> ;swpin_err_retn:
  3834                              <1> ;	mov	[u.error], eax
  3835                              <1> ;	stc
  3836                              <1> ;	retn
  3837                              <1> ;
  3838                              <1> ;swpin_snp_err:
  3839                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3840                              <1> ;	jmp	short swpin_err_retn
  3841                              <1> 
  3842                              <1> ; 24/12/2021
  3843                              <1> ; ('swap_out' procedure call is disabled)
  3844                              <1> 
  3845                              <1> ;swap_out:
  3846                              <1> 	; 10/06/2016
  3847                              <1> 	; 07/06/2016
  3848                              <1>         ; 23/05/2016
  3849                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3850                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3851                              <1> 	;
  3852                              <1> 	; INPUT -> 
  3853                              <1> 	;	none
  3854                              <1> 	;
  3855                              <1> 	; OUTPUT ->
  3856                              <1> 	;	EAX = Physical page address (which is swapped out
  3857                              <1> 	;	      for allocating a new page)
  3858                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3859                              <1> 	;		  or sector not present or drive not ready
  3860                              <1> 	;	     EAX = Error code
  3861                              <1> 	;	     [u.error] = EAX 
  3862                              <1> 	;		       = The last error code for the process
  3863                              <1> 	;		         (will be reset after returning to user)	  
  3864                              <1> 	;
  3865                              <1> 	; Modified Registers -> none (except EAX)
  3866                              <1> 	;
  3867                              <1> 
  3868                              <1> ;	cmp 	word [swpq_count], 1
  3869                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3870                              <1> ;
  3871                              <1> ;       ;cmp    dword [swp_drv], 1
  3872                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3873                              <1> ;
  3874                              <1> ;       cmp     dword [swpd_free], 1
  3875                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3876                              <1> ;
  3877                              <1> ;	push	ebx ; *
  3878                              <1> ;swpout_1:
  3879                              <1> ;	; 10/06/2016
  3880                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3881                              <1> ;	call	swap_queue_shift
  3882                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3883                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3884                              <1> ;				       ; pointer in the swap queue
  3885                              <1> ;	; EAX = PTE value of the page
  3886                              <1> ;	; EBX = PTE address of the page
  3887                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3888                              <1> ;	;
  3889                              <1> ;	; 07/06/2016
  3890                              <1> ;	; 19/05/2016
  3891                              <1> ;	; check this page is in timer events or not
  3892                              <1> ;	
  3893                              <1> ;swpout_timer_page_0:
  3894                              <1> ;	push	edx ; **
  3895                              <1> ;
  3896                              <1> ;	; 07/06/2016
  3897                              <1> ;	cmp	byte [timer_events], 0 
  3898                              <1> ;	jna	short swpout_2
  3899                              <1> ;	;
  3900                              <1> ;	mov	dl, [timer_events]
  3901                              <1> ;
  3902                              <1> ;	push	ecx ; ***
  3903                              <1> ;	push	ebx ; ****
  3904                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3905                              <1> ;			       ; structures 
  3906                              <1> ;swpout_timer_page_1:
  3907                              <1> ;	mov	cl, [ebx]
  3908                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3909                              <1> ;	jz	short swpout_timer_page_3
  3910                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3911                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3912                              <1> ;				; of the response byte address, to
  3913                              <1> ;				; get beginning of the page address)
  3914                              <1> ;	cmp	eax, ecx
  3915                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3916                              <1> ;	
  3917                              <1> ;	; !same page!
  3918                              <1> ;	;
  3919                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3920                              <1> ;	; This page will be used by the kernel to put timer event
  3921                              <1> ;	; response (signal return) byte at the requested address;
  3922                              <1> ;	; in order to prevent a possible wrong write (while
  3923                              <1> ;	; this page is swapped out) on physical memory,
  3924                              <1> ;	; we must protect this page against to be swapped out!
  3925                              <1> ;	;
  3926                              <1> ;	pop	ebx ; ****
  3927                              <1> ;	pop	ecx ; ***
  3928                              <1> ;	pop	edx ; **
  3929                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3930                              <1> ; 
  3931                              <1> ;swpout_timer_page_2:
  3932                              <1> ;	; 07/06/2016
  3933                              <1> ;	dec	dl
  3934                              <1> ;	jz	short swpout_timer_page_4
  3935                              <1> ;swpout_timer_page_3:
  3936                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3937                              <1> ;	;jnb	short swpout_timer_page_4
  3938                              <1> ;	add	ebx, 16
  3939                              <1> ;	jmp	short swpout_timer_page_1	
  3940                              <1> ;
  3941                              <1> ;swpout_timer_page_4:
  3942                              <1> ;	pop	ebx ; ****
  3943                              <1> ;	pop	ecx ; ***
  3944                              <1> ;swpout_2:
  3945                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  3946                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  3947                              <1> ;	;
  3948                              <1> ;	call	link_swap_block
  3949                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  3950                              <1> ;				       ; because [swpd_free] value
  3951                              <1> ;				       ; was checked at the beginging. 	
  3952                              <1> ;	pop	edx ; **
  3953                              <1> ;	pop	ebx ; *
  3954                              <1> ;	jmp	short swpout_nfspc_err 
  3955                              <1> ;swpout_3:
  3956                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  3957                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  3958                              <1> ;	;	
  3959                              <1> ;	push	esi ; **
  3960                              <1> ;	push	ecx ; ***
  3961                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  3962                              <1> ;	mov	esi, [swp_drv]	
  3963                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3964                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3965                              <1> ;		; size different than 512 bytes, logical disk sector
  3966                              <1> ;		; size is 512 bytes and disk writing procedure
  3967                              <1> ;		; will be performed for writing 4096 bytes
  3968                              <1> ;		; (2*2048, 8*512). 
  3969                              <1> ;	; ESI = Logical disk description table address
  3970                              <1> ;	; EBX = Buffer (Page) address
  3971                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3972                              <1> ;	; ECX = Sector count ; 8 sectors
  3973                              <1> ;	; edx = PTE address
  3974                              <1> ;	call	logical_disk_write
  3975                              <1> ;	; edx = PTE address
  3976                              <1> ;	pop	ecx ; sector address	
  3977                              <1> ;	jnc	short swpout_write_ok
  3978                              <1> ;	;
  3979                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  3980                              <1> ;swpout_dw_err:
  3981                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  3982                              <1> ;	mov	[u.error], eax
  3983                              <1> ;	jmp	short swpout_retn
  3984                              <1> ;	;
  3985                              <1> ;swpout_write_ok:
  3986                              <1> ;	; EBX = Buffer (page) address
  3987                              <1> ;	; EDX = Page Table Entry address
  3988                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  3989                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  3990                              <1> ;	mov 	[edx], ecx 
  3991                              <1> ;		; bit 0 = 0 (swapped page)
  3992                              <1> ;	mov	eax, ebx
  3993                              <1> ;swpout_retn:
  3994                              <1> ;	pop	ecx ; ***
  3995                              <1> ;	pop	esi ; **
  3996                              <1> ;	pop	ebx ; *
  3997                              <1> ;	retn
  3998                              <1> ;
  3999                              <1> ;;swpout_dnp_err:
  4000                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4001                              <1> ;;	jmp	short swpout_err_retn
  4002                              <1> ;swpout_nfspc_err:
  4003                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4004                              <1> ;swpout_err_retn:
  4005                              <1> ;	mov	[u.error], eax
  4006                              <1> ;	;stc
  4007                              <1> ;	retn
  4008                              <1> ;swpout_npts_err:
  4009                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4010                              <1> ;	pop	ebx
  4011                              <1> ;	jmp	short swpout_err_retn
  4012                              <1> ;swpout_im_err:
  4013                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4014                              <1> ;	jmp	short swpout_err_retn
  4015                              <1> 
  4016                              <1> ; 24/12/2021
  4017                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4018                              <1> 
  4019                              <1> ;swap_queue_shift:
  4020                              <1> 	; 26/03/2017
  4021                              <1> 	; 10/06/2016
  4022                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4023                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4024                              <1> 	;
  4025                              <1> 	; INPUT ->
  4026                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4027                              <1> 	;	      and process number combination (bit 0 to 11)
  4028                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4029                              <1> 	;	
  4030                              <1> 	; OUTPUT ->
  4031                              <1> 	;	If EBX input > 0 
  4032                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4033                              <1> 	; 	   from the tail to the head, up to entry offset
  4034                              <1> 	; 	   which points to EBX input value or nothing
  4035                              <1> 	;	   to do if EBX value is not found on the queue.
  4036                              <1> 	;	   (The entry -with EBX value- will be removed
  4037                              <1> 	;	   from the queue if it is found.)
  4038                              <1> 	;
  4039                              <1> 	;	   EAX = 0		
  4040                              <1> 	;
  4041                              <1> 	;	If EBX input = 0
  4042                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4043                              <1> 	; 	   from the tail to the head, if the PTE address
  4044                              <1> 	;	   which is pointed in head of the queue is marked
  4045                              <1> 	;	   as "accessed" or it is marked as "non present".
  4046                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4047                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4048                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4049                              <1> 	;	   -without dropping pointer of the PTE from 
  4050                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4051                              <1> 	;	   Pointer in the head will be moved into the tail,
  4052                              <1> 	;	   other PTEs will be shifted on head direction.)
  4053                              <1> 	;
  4054                              <1> 	;	   Swap queue will be shifted up to the first
  4055                              <1> 	;	   'present' or 'non accessed' page will be found
  4056                              <1> 	;	   (as pointed) on the queue head (then it will be
  4057                              <1>         ;          removed/dropped from the queue).
  4058                              <1> 	;
  4059                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4060                              <1> 	;		 (it's pointer -virtual address-) dropped
  4061                              <1> 	;		 (removed) from swap queue.
  4062                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4063                              <1> 	;	         which is (it's pointer -virtual address-)
  4064                              <1> 	;		 dropped (removed) from swap queue.
  4065                              <1> 	;
  4066                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4067                              <1> 	;
  4068                              <1> 	; Modified Registers -> EAX, EBX
  4069                              <1> 	;
  4070                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4071                              <1> ;	and	ax, ax
  4072                              <1> ;	jz	short swpqs_retn
  4073                              <1> ;	push	edi
  4074                              <1> ;	push	esi
  4075                              <1> ;	push	ecx
  4076                              <1> ;	mov	esi, swap_queue
  4077                              <1> ;	mov	ecx, eax
  4078                              <1> ;	or	ebx, ebx
  4079                              <1> ;	jz	short swpqs_7
  4080                              <1> ;swpqs_1:
  4081                              <1> ;	lodsd
  4082                              <1> ;	cmp	eax, ebx
  4083                              <1> ;	je	short swpqs_2
  4084                              <1> ;	loop	swpqs_1
  4085                              <1> ;	; 10/06/2016
  4086                              <1> ;	sub	eax, eax 
  4087                              <1> ;	jmp	short swpqs_6
  4088                              <1> ;swpqs_2:
  4089                              <1> ;	mov	edi, esi
  4090                              <1> ;	sub 	edi, 4
  4091                              <1> ;swpqs_3:
  4092                              <1> ;	dec	word [swpq_count]
  4093                              <1> ;	jz	short swpqs_5
  4094                              <1> ;swpqs_4:
  4095                              <1> ;	dec 	ecx
  4096                              <1> ;	rep	movsd	; shift up (to the head)
  4097                              <1> ;swpqs_5:
  4098                              <1> ;	xor	eax, eax
  4099                              <1> ;	mov	[edi], eax
  4100                              <1> ;swpqs_6:
  4101                              <1> ;	pop	ecx
  4102                              <1> ;	pop	esi
  4103                              <1> ;	pop	edi
  4104                              <1> ;swpqs_retn:
  4105                              <1> ;	retn		
  4106                              <1> ;swpqs_7:
  4107                              <1> ;	mov	edi, esi ; head
  4108                              <1> ;	lodsd
  4109                              <1> ;	; 20/07/2015
  4110                              <1> ;	mov	ebx, eax
  4111                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4112                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4113                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4114                              <1> ;		      ; ax = process number (1 to 4095)
  4115                              <1> ;	cmp	al, [u.uno]
  4116                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4117                              <1> ;	jne	short swpqs_8
  4118                              <1> ;	mov	eax, [u.pgdir]
  4119                              <1> ;	jmp	short swpqs_9
  4120                              <1> ;swpqs_8:
  4121                              <1> ;	; 09/06/2016
  4122                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4123                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4124                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4125                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4126                              <1> ;
  4127                              <1> ;	;shl	ax, 2
  4128                              <1> ;	shl	al, 2
  4129                              <1> ;	mov 	eax, [eax+p.upage-4]
  4130                              <1> ;	or	eax, eax
  4131                              <1> ;	jz	short swpqs_3 ; invalid upage
  4132                              <1> ;	add	eax, u.pgdir - user
  4133                              <1> ;			 ; u.pgdir value for the process
  4134                              <1> ;			 ; is in [eax]
  4135                              <1> ;	mov	eax, [eax]
  4136                              <1> ;	and	eax, eax
  4137                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4138                              <1> ;swpqs_9:
  4139                              <1> ;	push	edx
  4140                              <1> ;	; eax = page directory
  4141                              <1> ;	; ebx = virtual address
  4142                              <1> ;	call	get_pte
  4143                              <1> ;	mov	ebx, edx	; PTE address
  4144                              <1> ;	pop	edx
  4145                              <1> ;	; 10/06/2016
  4146                              <1> ;	jc	short swpqs_13 ; empty PDE
  4147                              <1> ;	; EAX = PTE value
  4148                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4149                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4150                              <1> ;			        ; from the queue (head)
  4151                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4152                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4153                              <1> ;			        ; from the queue (head) 	
  4154                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4155                              <1> ;	;jnz	short swpqs_11  ; present
  4156                              <1> ;			        ; accessed page
  4157                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4158                              <1> ;	jc	short swpqs_11  ; accessed page
  4159                              <1> ;
  4160                              <1> ;	dec	ecx
  4161                              <1> ;	mov	[swpq_count], cx
  4162                              <1> ;       jz      short swpqs_10
  4163                              <1> ;		; esi = head + 4
  4164                              <1> ;		; edi = head
  4165                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4166                              <1> ;swpqs_10:
  4167                              <1> ;	mov	[edi], ecx ; 0
  4168                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4169                              <1> ;
  4170                              <1> ;swpqs_11:
  4171                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4172                              <1> ;	; Rotation (head -> tail)
  4173                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4174                              <1> ;	jz	short swpqs_10
  4175                              <1> ;		; esi = head + 4
  4176                              <1> ;		; edi = head
  4177                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4178                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4179                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4180                              <1> ;
  4181                              <1> ;	mov	cx, [swpq_count]
  4182                              <1> ;
  4183                              <1> ;swpqs_12:
  4184                              <1> ;	mov	esi, swap_queue ; head
  4185                              <1> ;       jmp     swpqs_7
  4186                              <1> ;
  4187                              <1> ;swpqs_13:
  4188                              <1> ;	dec	ecx
  4189                              <1> ;	mov	[swpq_count], cx
  4190                              <1> ;       jz      swpqs_5
  4191                              <1> ;	jmp	short swpqs_12
  4192                              <1> 
  4193                              <1> ; 24/12/2021
  4194                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4195                              <1> 
  4196                              <1> ;add_to_swap_queue:
  4197                              <1> 	; 20/02/2017
  4198                              <1> 	; 20/07/2015
  4199                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4200                              <1> 	;
  4201                              <1> 	; Adds new page to swap queue
  4202                              <1> 	; (page directories and page tables must not be added
  4203                              <1> 	; to swap queue)	
  4204                              <1> 	;
  4205                              <1> 	; INPUT ->
  4206                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4207                              <1> 	;	[u.uno]
  4208                              <1> 	;	20/02/2017
  4209                              <1> 	;	(Linear address = CORE + user's virtual address)
  4210                              <1> 	;
  4211                              <1> 	; OUTPUT ->
  4212                              <1> 	;	EAX = [swpq_count]
  4213                              <1> 	;	      (after the PTE has been added)
  4214                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4215                              <1> 	;	      the PTE could not be added.
  4216                              <1> 	;
  4217                              <1> 	; Modified Registers -> EAX
  4218                              <1> 	;
  4219                              <1> ;	push	ebx
  4220                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4221                              <1> ;	mov	bl, [u.uno] ; current process number
  4222                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4223                              <1> ;				 ; it is already on the queue
  4224                              <1> ;		; then add it to the tail of the queue
  4225                              <1> ;	movzx	eax, word [swpq_count]
  4226                              <1> ;	cmp	ax, 1024
  4227                              <1> ;	jb	short atsq_1
  4228                              <1> ;	sub	ax, ax
  4229                              <1> ;	pop	ebx
  4230                              <1> ;	retn
  4231                              <1> ;atsq_1:
  4232                              <1> ;	push	esi
  4233                              <1> ;	mov	esi, swap_queue
  4234                              <1> ;	and	ax, ax
  4235                              <1> ;	jz	short atsq_2
  4236                              <1> ;	shl	ax, 2	; convert to offset
  4237                              <1> ;	add	esi, eax
  4238                              <1> ;	shr	ax, 2
  4239                              <1> ;atsq_2:
  4240                              <1> ;	inc	ax
  4241                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4242                              <1> ;	mov	[swpq_count], ax
  4243                              <1> ;	pop	esi
  4244                              <1> ;	pop	ebx
  4245                              <1> ;	retn
  4246                              <1> 
  4247                              <1> ; 24/12/2021
  4248                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4249                              <1> 
  4250                              <1> ;unlink_swap_block:
  4251                              <1> 	; 15/09/2015
  4252                              <1> 	; 30/04/2015
  4253                              <1> 	; 18/04/2015
  4254                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4255                              <1> 	;
  4256                              <1> 	; INPUT -> 
  4257                              <1> 	;	EAX = swap disk/file offset address
  4258                              <1> 	;	      (bit 1 to bit 31)
  4259                              <1> 	; OUTPUT ->
  4260                              <1> 	;	[swpd_free] is increased
  4261                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4262                              <1> 	;
  4263                              <1> 	; Modified Registers -> EAX
  4264                              <1> 	;
  4265                              <1> ;	push	ebx
  4266                              <1> ;	push	edx
  4267                              <1> ;	;
  4268                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4269                              <1> ;				     ; 3 bits right
  4270                              <1> ;				     ; to get swap block/page number
  4271                              <1> ;	mov	edx, eax
  4272                              <1> ;	; 15/09/2015
  4273                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4274                              <1> ;				     ; (1 allocation bit = 1 page)
  4275                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4276                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4277                              <1> ;				     ; (to get 32 bit position)			
  4278                              <1> ;	;
  4279                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4280                              <1> ;	add	ebx, edx
  4281                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4282                              <1> ;				     ; (allocation bit position)	 
  4283                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4284                              <1> ;				     ; than the address in 'swpd_next' ?
  4285                              <1> ;				     ; (next/first free block value)		
  4286                              <1> ;	jnb	short uswpbl_1	     ; no	
  4287                              <1> ;	mov	[swpd_next], eax     ; yes	
  4288                              <1> ;uswpbl_1:
  4289                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4290                              <1> ;				     ; set relevant bit to 1.
  4291                              <1> ;				     ; set CF to the previous bit value	
  4292                              <1> ;	cmc			     ; complement carry flag	
  4293                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4294                              <1> ;				     ; if the block is already deallocated
  4295                              <1> ;				     ; before.	
  4296                              <1> ;       inc     dword [swpd_free]
  4297                              <1> ;uswpbl_2:
  4298                              <1> ;	pop	edx
  4299                              <1> ;	pop	ebx
  4300                              <1> ;	retn
  4301                              <1> 
  4302                              <1> ; 24/12/2021
  4303                              <1> ; ('link_swap_block' procedure call is disabled)
  4304                              <1> 
  4305                              <1> ;link_swap_block:
  4306                              <1> 	; 01/07/2015
  4307                              <1> 	; 18/04/2015
  4308                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4309                              <1> 	;
  4310                              <1> 	; INPUT -> none
  4311                              <1> 	;
  4312                              <1> 	; OUTPUT ->
  4313                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4314                              <1> 	;	      in sectors (corresponding 
  4315                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4316                              <1> 	;
  4317                              <1> 	;	CF = 1 and EAX = 0 
  4318                              <1> 	; 		   if there is not a free block to be allocated	
  4319                              <1> 	;
  4320                              <1> 	; Modified Registers -> none (except EAX)
  4321                              <1> 	;
  4322                              <1> 
  4323                              <1> ;	;mov	eax, [swpd_free]
  4324                              <1> ;	;and	eax, eax
  4325                              <1> ;	;jz	short out_of_swpspc
  4326                              <1> ;	;
  4327                              <1> ;	push	ebx
  4328                              <1> ;	push	ecx
  4329                              <1> ;	;
  4330                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4331                              <1> ;	mov	ecx, ebx
  4332                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4333                              <1> ;				 ; next_free_swap_block >> 5
  4334                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4335                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4336                              <1> ;lswbl_scan:
  4337                              <1> ;	cmp	ebx, ecx
  4338                              <1> ;	ja	short lswbl_notfound
  4339                              <1> ;	;
  4340                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4341                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4342                              <1> ;			   ; loads the destination with an index to
  4343                              <1> ;			   ; first set bit. (0 -> 31) 
  4344                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4345                              <1> ;	; 01/07/2015
  4346                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4347                              <1> ;			 ;
  4348                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4349                              <1> ;			 ;	  with value of 1 means 
  4350                              <1> ;			 ;	  the corresponding page is free 
  4351                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4352                              <1> ;	add	ebx, 4
  4353                              <1> ;			 ; We return back for searching next page block
  4354                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4355                              <1> ;			 ;	 we always will find at least 1 free block here.
  4356                              <1> ;	jmp    	short lswbl_scan
  4357                              <1> ;	;
  4358                              <1> ;lswbl_notfound:	
  4359                              <1> ;	sub	ecx, swap_alloc_table
  4360                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4361                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4362                              <1> ;	xor	eax, eax
  4363                              <1> ;	mov	[swpd_free], eax
  4364                              <1> ;	stc
  4365                              <1> ;lswbl_ok:
  4366                              <1> ;	pop	ecx
  4367                              <1> ;	pop	ebx
  4368                              <1> ;	retn
  4369                              <1> ;	;
  4370                              <1> ;;out_of_swpspc:
  4371                              <1> ;;	stc
  4372                              <1> ;;	retn
  4373                              <1> ;
  4374                              <1> ;lswbl_found:
  4375                              <1> ;	mov	ecx, ebx
  4376                              <1> ;	sub	ecx, swap_alloc_table
  4377                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4378                              <1> ;				 ; address/offset (to the next)
  4379                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4380                              <1> ;	;
  4381                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4382                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4383                              <1> ;				 ; in the destination.
  4384                              <1> ;				 ;
  4385                              <1> ;				 ; Reset the bit which is corresponding to the 
  4386                              <1> ;				 ; (just) allocated block.
  4387                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4388                              <1> ;	add	eax, ecx	 ; = block number
  4389                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4390                              <1> ;				 ; 1 block =  8 sectors
  4391                              <1> ;	;
  4392                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4393                              <1> ;	;
  4394                              <1> ;	; NOTE: The relevant page table entry will be updated
  4395                              <1> ;	;       according to this EAX value...
  4396                              <1> ;	;
  4397                              <1> ;	jmp	short lswbl_ok
  4398                              <1> 
  4399                              <1> ; 24/12/2021
  4400                              <1> ; ('logical_disk_read' procedure call is disabled)
  4401                              <1> 
  4402                              <1> ;logical_disk_read:
  4403                              <1> 	; 20/07/2015
  4404                              <1> 	; 09/03/2015 (temporary code here)
  4405                              <1> 	;
  4406                              <1> 	; INPUT ->
  4407                              <1> 	; 	ESI = Logical disk description table address
  4408                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4409                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4410                              <1> 	; 	ECX = Sector count
  4411                              <1> 	;
  4412                              <1> 	;
  4413                              <1> ;	retn
  4414                              <1> 
  4415                              <1> ; 24/12/2021
  4416                              <1> ; ('logical_disk_write' procedure call is disabled)
  4417                              <1> 
  4418                              <1> ;logical_disk_write:
  4419                              <1> 	; 20/07/2015
  4420                              <1> 	; 09/03/2015 (temporary code here)
  4421                              <1> 	;
  4422                              <1> 	; INPUT ->
  4423                              <1> 	; 	ESI = Logical disk description table address
  4424                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4425                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4426                              <1> 	; 	ECX = Sector count
  4427                              <1> 	;
  4428                              <1> ;	retn
  4429                              <1> 
  4430                              <1> get_physical_addr:
  4431                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4432                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4433                              <1> 	; 18/10/2015
  4434                              <1> 	; 29/07/2015
  4435                              <1> 	; 20/07/2015
  4436                              <1> 	; 04/06/2015
  4437                              <1> 	; 20/05/2015
  4438                              <1> 	; 28/04/2015
  4439                              <1> 	; 18/04/2015
  4440                              <1> 	; Get physical address
  4441                              <1> 	;     (allocates a new page for user if it is not present)
  4442                              <1> 	;	
  4443                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4444                              <1> 	; (buffer) address to physical address (of the buffer).)
  4445                              <1> 	; ('sys write', 'sys read' system calls...)
  4446                              <1> 	;
  4447                              <1> 	; INPUT ->
  4448                              <1> 	;	EBX = virtual address
  4449                              <1> 	;	u.pgdir = page directory (physical) address
  4450                              <1> 	;
  4451                              <1> 	; OUTPUT ->
  4452                              <1> 	;	EAX = physical address 
  4453                              <1> 	;	EBX = linear address	
  4454                              <1> 	;	EDX = physical address of the page frame
  4455                              <1> 	;	      (with attribute bits)
  4456                              <1> 	;	ECX = byte count within the page frame
  4457                              <1> 	;
  4458                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4459                              <1> 	;
  4460                              <1> 
  4461                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4462 000031D4 A1[4B6F0000]        <1> 	mov	eax, [u.pgdir]
  4463                              <1> 
  4464                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4465                              <1> 	
  4466 000031D9 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4467                              <1> 	;
  4468                              <1> 	;mov	eax, [u.pgdir]
  4469 000031DF E816FDFFFF          <1> 	call	get_pte
  4470                              <1> 		; EDX = Page table entry address (if CF=0)
  4471                              <1> 	        ;       Page directory entry address (if CF=1)
  4472                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4473                              <1> 		; EAX = Page table entry value (page address)
  4474                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4475 000031E4 731C                <1> 	jnc	short gpa_1
  4476                              <1> 	;
  4477 000031E6 E8FDFBFFFF          <1> 	call	allocate_page
  4478 000031EB 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4479                              <1> gpa_0:
  4480 000031ED E867FCFFFF          <1> 	call 	clear_page
  4481                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4482 000031F2 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4483                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4484                              <1> 			   ; (user, writable, present page)	
  4485 000031F4 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4486 000031F6 A1[4B6F0000]        <1> 	mov	eax, [u.pgdir]	
  4487 000031FB E8FAFCFFFF          <1> 	call	get_pte
  4488 00003200 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4489                              <1> gpa_1:
  4490                              <1> 	; EAX = PTE value, EDX = PTE address
  4491 00003202 A801                <1> 	test 	al, PTE_A_PRESENT
  4492 00003204 750A                <1> 	jnz	short gpa_3
  4493 00003206 09C0                <1> 	or	eax, eax
  4494 00003208 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4495                              <1> 
  4496                              <1> ; 24/12/2021
  4497                              <1> ; ('reload_page' procedure call is disabled)
  4498 0000320A EB2C                <1> 	jmp	short gpa_im_err
  4499                              <1> 
  4500                              <1> 	; 20/07/2015
  4501                              <1> ;	push	ebp
  4502                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4503                              <1> ;	; reload swapped page
  4504                              <1> ;	call	reload_page ; 28/04/2015
  4505                              <1> ;	pop	ebp
  4506                              <1> ;	jc	short gpa_retn
  4507                              <1> gpa_2:
  4508                              <1> ; 24/12/2021
  4509                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4510                              <1> 
  4511                              <1> 	; 20/07/2015
  4512                              <1> 	; 20/05/2015
  4513                              <1> 	; add this page to swap queue
  4514                              <1> ;	push	eax 
  4515                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4516                              <1> ;	call 	add_to_swap_queue
  4517                              <1> ;	pop	eax
  4518                              <1> 		; PTE address in EDX
  4519                              <1> 		; virtual address in EBX
  4520                              <1> 	; EAX = memory page address
  4521 0000320C 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4522                              <1> 				  ; present flag, bit 0 = 1
  4523                              <1> 				  ; user flag, bit 2 = 1	
  4524                              <1> 				  ; writable flag, bit 1 = 1
  4525 0000320E 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4526                              <1> gpa_3:
  4527                              <1> 	; 18/10/2015
  4528 00003210 89D9                <1> 	mov	ecx, ebx
  4529 00003212 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4530 00003218 89C2                <1> 	mov 	edx, eax
  4531 0000321A 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4532 0000321E 01C8                <1> 	add	eax, ecx
  4533 00003220 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4534 00003222 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4535 00003228 F8                  <1> 	clc
  4536                              <1> gpa_retn:
  4537 00003229 C3                  <1> 	retn	
  4538                              <1> gpa_4:	
  4539 0000322A E8B9FBFFFF          <1> 	call	allocate_page
  4540 0000322F 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4541 00003231 E823FCFFFF          <1> 	call	clear_page
  4542 00003236 EBD4                <1> 	jmp	short gpa_2
  4543                              <1> 
  4544                              <1> gpa_im_err:	
  4545 00003238 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4546                              <1> 				  ; Major error = 0 (No protection fault)	
  4547 0000323D C3                  <1> 	retn
  4548                              <1> 
  4549                              <1> ; 24/12/2021
  4550                              <1> ; ('reload_page' procedure call is disabled)
  4551                              <1> 
  4552                              <1> ;reload_page:
  4553                              <1> 	; 20/07/2015
  4554                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4555                              <1> 	;
  4556                              <1> 	; Reload (Restore) swapped page at memory
  4557                              <1> 	;
  4558                              <1> 	; INPUT -> 
  4559                              <1> 	;	EBP = Virtual (linear) memory address
  4560                              <1> 	;	EAX = PTE value (swap disk sector address)
  4561                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4562                              <1> 	; OUTPUT ->
  4563                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4564                              <1> 	;
  4565                              <1> 	;	CF = 1 and EAX = error code
  4566                              <1> 	;
  4567                              <1> 	; Modified Registers -> none (except EAX)
  4568                              <1> 	;
  4569                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4570                              <1> ;	push	ebx      ;
  4571                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4572                              <1> ;	call	allocate_page
  4573                              <1> ;	jc	short rlp_im_err
  4574                              <1> ;	xchg 	eax, ebx	
  4575                              <1> ;	; EBX = Physical memory (page) address
  4576                              <1> ;	; EAX = Swap disk (offset) address
  4577                              <1> ;	; EBP = Virtual (linear) memory address
  4578                              <1> ;	call	swap_in
  4579                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4580                              <1> ;	mov	eax, ebx	
  4581                              <1> ;rlp_retn:
  4582                              <1> ;	pop	ebx
  4583                              <1> ;	retn
  4584                              <1> ;	
  4585                              <1> ;rlp_im_err:	
  4586                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4587                              <1> ;				  ; Major error = 0 (No protection fault)	
  4588                              <1> ;	jmp	short rlp_retn
  4589                              <1> ;
  4590                              <1> ;rlp_swp_err:
  4591                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4592                              <1> ;	jmp	short rlp_retn
  4593                              <1> 
  4594                              <1> copy_page_dir:
  4595                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4596                              <1> 	; 19/09/2015
  4597                              <1> 	; temporary - 07/09/2015
  4598                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4599                              <1> 	;
  4600                              <1> 	; INPUT -> 
  4601                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4602                              <1> 	;		    page directory.
  4603                              <1> 	; OUTPUT ->
  4604                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4605                              <1> 	;	       page directory.
  4606                              <1> 	;	(New page directory with new page table entries.)
  4607                              <1> 	;	(New page tables with read only copies of the parent's
  4608                              <1> 	;	pages.)
  4609                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4610                              <1> 	;
  4611                              <1> 	; Modified Registers -> none (except EAX)
  4612                              <1> 	;
  4613 0000323E E8A5FBFFFF          <1> 	call	allocate_page
  4614 00003243 723E                <1> 	jc	short cpd_err
  4615                              <1> 	;
  4616 00003245 55                  <1> 	push	ebp ; 20/07/2015
  4617 00003246 56                  <1> 	push	esi
  4618 00003247 57                  <1> 	push	edi
  4619 00003248 53                  <1> 	push	ebx
  4620 00003249 51                  <1> 	push	ecx
  4621 0000324A 8B35[4B6F0000]      <1> 	mov	esi, [u.pgdir]
  4622 00003250 89C7                <1> 	mov	edi, eax
  4623 00003252 50                  <1> 	push	eax ; save child's page directory address
  4624                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4625                              <1> 	; (use same system space for all user page tables) 
  4626 00003253 A5                  <1> 	movsd
  4627 00003254 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4628 00003259 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4629                              <1> cpd_0:	
  4630 0000325E AD                  <1> 	lodsd
  4631                              <1> 	;or	eax, eax
  4632                              <1>         ;jnz	short cpd_1
  4633 0000325F A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4634 00003261 7508                <1> 	jnz	short cpd_1
  4635                              <1>  	; (virtual address at the end of the page table)	
  4636 00003263 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4637 00003269 EB0F                <1> 	jmp	short cpd_2
  4638                              <1> cpd_1:	
  4639 0000326B 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4640 0000326F 89C3                <1> 	mov	ebx, eax
  4641                              <1> 	; EBX = Parent's page table address
  4642 00003271 E81F000000          <1> 	call	copy_page_table
  4643 00003276 720C                <1> 	jc	short cpd_p_err
  4644                              <1> 	; EAX = Child's page table address
  4645 00003278 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4646                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4647                              <1> 			 ; (present, writable, user)
  4648                              <1> cpd_2:
  4649 0000327A AB                  <1> 	stosd
  4650 0000327B E2E1                <1> 	loop	cpd_0
  4651                              <1> 	;
  4652 0000327D 58                  <1> 	pop	eax  ; restore child's page directory address
  4653                              <1> cpd_3:
  4654 0000327E 59                  <1> 	pop	ecx
  4655 0000327F 5B                  <1> 	pop	ebx
  4656 00003280 5F                  <1> 	pop	edi
  4657 00003281 5E                  <1> 	pop	esi
  4658 00003282 5D                  <1> 	pop	ebp
  4659                              <1> cpd_err:
  4660 00003283 C3                  <1> 	retn
  4661                              <1> cpd_p_err:
  4662                              <1> 	; release the allocated pages missing (recover free space)
  4663 00003284 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4664 00003285 8B1D[4B6F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4665 0000328B E888FCFFFF          <1> 	call 	deallocate_page_dir
  4666 00003290 29C0                <1> 	sub	eax, eax ; 0
  4667 00003292 F9                  <1> 	stc
  4668 00003293 EBE9                <1> 	jmp	short cpd_3	
  4669                              <1> 
  4670                              <1> copy_page_table:
  4671                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4672                              <1> 	; 19/09/2015
  4673                              <1> 	; temporary - 07/09/2015
  4674                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4675                              <1> 	;
  4676                              <1> 	; INPUT -> 
  4677                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4678                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4679                              <1> 	; OUTPUT ->
  4680                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4681                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4682                              <1> 	;	CF = 1 -> error 
  4683                              <1> 	;
  4684                              <1> 	; Modified Registers -> EBP (except EAX)
  4685                              <1> 	;
  4686 00003295 E84EFBFFFF          <1> 	call	allocate_page
  4687 0000329A 7244                <1> 	jc	short cpt_err
  4688                              <1> 	;
  4689 0000329C 50                  <1> 	push	eax ; *
  4690                              <1> 	;push 	ebx
  4691 0000329D 56                  <1> 	push	esi
  4692 0000329E 57                  <1> 	push	edi
  4693 0000329F 52                  <1> 	push	edx
  4694 000032A0 51                  <1> 	push	ecx
  4695                              <1> 	;
  4696 000032A1 89DE                <1> 	mov	esi, ebx
  4697 000032A3 89C7                <1> 	mov	edi, eax
  4698 000032A5 89C2                <1> 	mov	edx, eax
  4699 000032A7 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4700                              <1> cpt_0:
  4701 000032AD AD                  <1> 	lodsd
  4702 000032AE A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4703                              <1> 	;jnz	short cpt_1 (*)
  4704                              <1> 	; 24/12/2021
  4705                              <1> 	;and	eax, eax (*)
  4706 000032B0 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4707                              <1> 	
  4708                              <1> ; 24/12/2021
  4709                              <1> ; ('reload_page' procedure call is disabled)
  4710                              <1> ;
  4711                              <1> ;	; ebp = virtual (linear) address of the memory page
  4712                              <1> ;	call	reload_page ; 28/04/2015
  4713                              <1> ;	jc	short cpt_p_err
  4714                              <1> cpt_1:
  4715 000032B2 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4716 000032B6 89C1                <1> 	mov	ecx, eax
  4717                              <1> 	; Allocate a new page for the child process
  4718 000032B8 E82BFBFFFF          <1> 	call	allocate_page
  4719 000032BD 721C                <1> 	jc	short cpt_p_err
  4720 000032BF 57                  <1> 	push	edi
  4721 000032C0 56                  <1> 	push	esi
  4722 000032C1 89CE                <1> 	mov	esi, ecx
  4723 000032C3 89C7                <1> 	mov	edi, eax
  4724 000032C5 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4725 000032CA F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4726 000032CC 5E                  <1> 	pop	esi
  4727 000032CD 5F                  <1> 	pop	edi
  4728                              <1> 	; 
  4729                              <1> ; 24/12/2021
  4730                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4731                              <1> ;
  4732                              <1> ;	push	ebx
  4733                              <1> ;	push	eax
  4734                              <1> ;	mov	ebx, ebp
  4735                              <1> ;	; ebx = virtual address of the memory page
  4736                              <1> ;	call	add_to_swap_queue
  4737                              <1> ;	pop	eax
  4738                              <1> ;	pop	ebx
  4739                              <1> 	;
  4740                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4741 000032CE 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4742                              <1> cpt_2:
  4743 000032D0 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4744                              <1> 	;
  4745 000032D1 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4746                              <1> 	;
  4747 000032D7 39D7                <1> 	cmp	edi, edx
  4748 000032D9 72D2                <1> 	jb	short cpt_0
  4749                              <1> cpt_p_err:
  4750 000032DB 59                  <1> 	pop	ecx
  4751 000032DC 5A                  <1> 	pop	edx
  4752 000032DD 5F                  <1> 	pop	edi
  4753 000032DE 5E                  <1> 	pop	esi
  4754                              <1> 	;pop	ebx
  4755 000032DF 58                  <1> 	pop	eax ; *
  4756                              <1> cpt_err:
  4757 000032E0 C3                  <1> 	retn
  4758                              <1> 
  4759                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4760                              <1> 
  4761                              <1> ;; Data:
  4762                              <1> 
  4763                              <1> ; 09/03/2015
  4764                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4765                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4766                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4767                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4768                              <1> ;swpd_next:  dd 0 ; next free page block
  4769                              <1> ;swpd_last:  dd 0 ; last swap page block
  1987                                  %include 'sysdefs.inc' ; 09/03/2015
  1988                              <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC
  1989                              <1> ; Last Modification: 12/02/2022
  1990                              <1> ;
  1991                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  1992                              <1> ; (Modified from 
  1993                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  1994                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  1995                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  1996                              <1> ; ----------------------------------------------------------------------------
  1997                              <1> ;
  1998                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  1999                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2000                              <1> ; <Bell Laboratories (17/3/1972)>
  2001                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2002                              <1> ;
  2003                              <1> ; ****************************************************************************
  2004                              <1> 
  2005                              <1> nproc 	equ	16  ; number of processes
  2006                              <1> nfiles 	equ	50
  2007                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2008                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2009                              <1> 
  2010                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2011                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2012                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2013                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2014                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2015                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2016                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2017                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2018                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2019                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2020                              <1> 	; '/core' dump file size = 32768 bytes
  2021                              <1>  
  2022                              <1> ; 08/03/2014 
  2023                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2024                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2025                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2026                              <1> 
  2027                              <1> ; 30/08/2013
  2028                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2029                              <1> 
  2030                              <1> ; 05/02/2014
  2031                              <1> ; process status
  2032                              <1> ;SFREE 	equ 0
  2033                              <1> ;SRUN	equ 1
  2034                              <1> ;SWAIT	equ 2
  2035                              <1> ;SZOMB	equ 3
  2036                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2037                              <1> 
  2038                              <1> ; 09/03/2015
  2039                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2040                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2041                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2042                              <1> 
  2043                              <1> ; 17/09/2015
  2044                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2045                              <1> 
  2046                              <1> ; 21/09/2015 (36) 
  2047                              <1> ; 01/07/2015 (35)
  2048                              <1> ; 14/07/2013 (0-34)
  2049                              <1> ; UNIX v1 system calls
  2050                              <1> _rele 	equ 0
  2051                              <1> _exit 	equ 1
  2052                              <1> _fork 	equ 2
  2053                              <1> _read 	equ 3
  2054                              <1> _write	equ 4
  2055                              <1> _open	equ 5
  2056                              <1> _close 	equ 6
  2057                              <1> _wait 	equ 7
  2058                              <1> _creat 	equ 8
  2059                              <1> _link 	equ 9
  2060                              <1> _unlink	equ 10
  2061                              <1> _exec	equ 11
  2062                              <1> _chdir	equ 12
  2063                              <1> _time 	equ 13
  2064                              <1> _mkdir 	equ 14
  2065                              <1> _chmod	equ 15
  2066                              <1> _chown	equ 16
  2067                              <1> _break	equ 17
  2068                              <1> _stat	equ 18
  2069                              <1> _seek	equ 19
  2070                              <1> _tell 	equ 20
  2071                              <1> _mount	equ 21
  2072                              <1> _umount	equ 22
  2073                              <1> _setuid	equ 23
  2074                              <1> _getuid	equ 24
  2075                              <1> _stime	equ 25
  2076                              <1> _quit	equ 26	
  2077                              <1> _intr	equ 27
  2078                              <1> _fstat	equ 28
  2079                              <1> _emt 	equ 29
  2080                              <1> _mdate 	equ 30
  2081                              <1> _stty 	equ 31
  2082                              <1> _gtty	equ 32
  2083                              <1> _ilgins	equ 33
  2084                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2085                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2086                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2087                              <1> 
  2088                              <1> %macro sys 1-4
  2089                              <1>     ; 13/04/2015
  2090                              <1>     ; Retro UNIX 386 v1 system call.		
  2091                              <1>     mov eax, %1
  2092                              <1>     %if %0 >= 2   
  2093                              <1>         mov ebx, %2
  2094                              <1>         %if %0 >= 3    
  2095                              <1>             mov ecx, %3
  2096                              <1>             %if %0 = 4
  2097                              <1>                mov edx, %4   
  2098                              <1>             %endif
  2099                              <1>         %endif
  2100                              <1>     %endif
  2101                              <1>     int 30h	   
  2102                              <1> %endmacro
  2103                              <1> 
  2104                              <1> ; 13/05/2015 - ERROR CODES
  2105                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2106                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2107                              <1> ; 14/05/2015
  2108                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2109                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2110                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2111                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2112                              <1> ; 16/05/2015		
  2113                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2114                              <1> ; 18/05/2015
  2115                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2116                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2117                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2118                              <1> ; 07/06/2015
  2119                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2120                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2121                              <1> ; 09/06/2015
  2122                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2123                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2124                              <1> ; 16/06/2015
  2125                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2126                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2127                              <1> ; 22/06/2015
  2128                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2129                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2130                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2131                              <1> ; 23/06/2015
  2132                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2133                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2134                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2135                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2136                              <1> ; 27/06/2015
  2137                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2138                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2139                              <1> ; 29/06/2015
  2140                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2141                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2142                              <1> ; 12/02/2022 
  2143                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2144                              <1> ; 10/10/2016
  2145                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2146                              <1> ; 18/05/2016
  2147                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2148                              <1> ; 15/10/2016
  2149                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2150                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2151                              <1> ; 16/10/2016
  2152                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2153                              <1> ; 08/02/2022
  2154                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error	
  2155                              <1> 
  2156                              <1> ; 26/08/2015
  2157                              <1> ; 24/07/2015
  2158                              <1> ; 24/06/2015
  2159                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2160                              <1> ; 01/07/2015
  2161                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2162                              <1> ;	 					 		
  1988                                  %include 'u0.s'        ; 15/03/2015
  1989                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYS0.INC
  1990                              <1> ; Last Modification: 23/02/2022
  1991                              <1> ; ----------------------------------------------------------------------------
  1992                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1993                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1994                              <1> ;
  1995                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  1996                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  1997                              <1> ; <Bell Laboratories (17/3/1972)>
  1998                              <1> ; <Preliminary Release of UNIX Implementation Document>
  1999                              <1> ;
  2000                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2001                              <1> ;
  2002                              <1> ; ****************************************************************************
  2003                              <1> ; 21/11/2015
  2004                              <1> 
  2005                              <1> sys_init:
  2006                              <1> 	; 23/02/2022
  2007                              <1> 	; 04/02/2022
  2008                              <1> 	; 18/10/2015
  2009                              <1> 	; 28/08/2015
  2010                              <1> 	; 24/08/2015
  2011                              <1> 	; 14/08/2015
  2012                              <1> 	; 24/07/2015 
  2013                              <1> 	; 02/07/2015
  2014                              <1> 	; 01/07/2015
  2015                              <1> 	; 23/06/2015
  2016                              <1> 	; 15/04/2015
  2017                              <1> 	; 13/04/2015
  2018                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2019                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2020                              <1> 	;
  2021                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2022                              <1> 	;
  2023                              <1> 	; 14/02/2014
  2024                              <1> 	; 14/07/2013
  2025 000032E1 66B82900            <1> 	mov	ax, 41
  2026 000032E5 66A3[E86E0000]      <1> 	mov	[rootdir], ax
  2027 000032EB 66A3[FC6E0000]      <1> 	mov	[u.cdir], ax
  2028 000032F1 2401                <1> 	and	al, 1 ; 15/04/2015
  2029 000032F3 A2[416F0000]        <1> 	mov	[u.uno], al
  2030 000032F8 66A3[E66E0000]      <1> 	mov	[mpid], ax
  2031 000032FE 66A3[166C0000]      <1> 	mov	[p.pid], ax
  2032 00003304 A2[766C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2033                              <1> 	;
  2034 00003309 B004                <1> 	mov	al, time_count ; 30/08/2013
  2035 0000330B A2[346F0000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2036                              <1> 	; 02/07/2015
  2037 00003310 A1[486B0000]        <1> 	mov	eax, [k_page_dir]
  2038                              <1> 	;sub	eax, eax
  2039 00003315 A3[4B6F0000]        <1> 	mov	[u.pgdir], eax ; reset
  2040                              <1> 	; 18/10/2015
  2041                              <1> 	;mov	[u.ppgdir], eax ; 0
  2042                              <1>         ;
  2043                              <1> 	; 23/02/2022
  2044                              <1>  	;call	epoch
  2045                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2046                              <1> 	; 17/07/2013
  2047 0000331A E8A2060000          <1> 	call 	bf_init ; buffer initialization
  2048                              <1> 	; 23/02/2022
  2049                              <1> 	; (save sysinit time on sb0)
  2050 0000331F E83C030000          <1> 	call	epoch
  2051 00003324 A3[3C7D0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2052                              <1> 	; 23/06/2015
  2053 00003329 E8BAFAFFFF          <1> 	call	allocate_page
  2054                              <1> 	;;jc	error
  2055                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2056                              <1> 	; 04/02/2022
  2057 0000332E 7305                <1> 	jnc	short sysinit_1
  2058 00003330 E99C000000          <1> 	jmp	panic
  2059                              <1> sysinit_1:
  2060 00003335 A3[426F0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2061 0000333A A3[866C0000]        <1> 	mov	[p.upage], eax
  2062                              <1> 	;
  2063 0000333F E815FBFFFF          <1> 	call	clear_page
  2064                              <1> 	;
  2065                              <1> 	; 14/08/2015
  2066 00003344 FA                  <1> 	cli
  2067                              <1> 	; 14/03/2015
  2068                              <1> 	; 17/01/2014
  2069 00003345 E8E3010000          <1> 	call	sp_init ; serial port initialization
  2070                              <1> 	; 14/08/2015
  2071 0000334A FB                  <1> 	sti
  2072                              <1> 	;
  2073                              <1> 	; 30/06/2015
  2074                              <1> 	;mov	esi, kernel_init_ok_msg
  2075                              <1> 	;call 	print_msg
  2076                              <1> 	;
  2077 0000334B 30DB                <1> 	xor	bl, bl ; video page 0
  2078                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2079 0000334D E81A2E0000          <1> 	call 	vp_clr  ; 17/07/2013
  2080 00003352 FEC3                <1> 	inc	bl
  2081 00003354 80FB08              <1> 	cmp	bl, 8
  2082 00003357 72F4                <1> 	jb	short vp_clr_nxt
  2083                              <1> 	;
  2084                              <1> 	; 24/07/2015
  2085                              <1> 	;push	KDATA
  2086                              <1>         ;push	esp
  2087                              <1> 	;mov	[tss.esp0], esp
  2088                              <1>         ;mov	word [tss.ss0], KDATA
  2089                              <1> 	;
  2090                              <1> 	; 24/08/2015
  2091                              <1> 	;; temporary (01/07/2015)
  2092 00003359 C605[346F0000]04    <1> 	mov	byte [u.quant], time_count ; 4 
  2093                              <1> 			       ; it is not needed here !
  2094                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2095 00003360 FE0D[EF6E0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2096                              <1> 			      ; 0 = executing a system call
  2097                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2098                              <1> 	;
  2099                              <1> 	;;; 06/08/2015
  2100                              <1> 	;;;call	getch ; wait for a key stroke
  2101                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2102                              <1> ;;sys_init_msg_wait:
  2103                              <1> ;;	push 	ecx
  2104                              <1> ;;	mov	al, 1
  2105                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2106                              <1> ;;	call	getc_n
  2107                              <1> ;;	pop	ecx
  2108                              <1> ;;	jnz	short sys_init_msg_ok
  2109                              <1> ;;	loop	sys_init_msg_wait
  2110                              <1> 	;
  2111                              <1> ;;sys_init_msg_ok:
  2112                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2113 00003366 6A10                <1> 	push	KDATA ; ss
  2114 00003368 54                  <1> 	push	esp
  2115 00003369 9C                  <1> 	pushfd
  2116 0000336A 6A08                <1> 	push	KCODE ; cs
  2117 0000336C 68[A0330000]        <1> 	push	init_exec ; eip
  2118 00003371 8925[F06E0000]      <1> 	mov	[u.sp], esp
  2119 00003377 1E                  <1> 	push	ds
  2120 00003378 06                  <1> 	push	es
  2121 00003379 0FA0                <1> 	push	fs
  2122 0000337B 0FA8                <1> 	push	gs	
  2123 0000337D 60                  <1> 	pushad
  2124 0000337E 8925[F46E0000]      <1> 	mov	[u.usp], esp
  2125 00003384 E8731B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2126                              <1> 		      ; and interrupt return components (for IRET)
  2127 00003389 61                  <1> 	popad
  2128 0000338A 6658                <1> 	pop	ax ; gs
  2129 0000338C 6658                <1> 	pop	ax ; fs
  2130 0000338E 6658                <1> 	pop	ax ; es
  2131 00003390 6658                <1> 	pop	ax ; ds	
  2132 00003392 58                  <1> 	pop	eax ; eip (init_exec)
  2133 00003393 6658                <1> 	pop	ax ; cs (KCODE)
  2134 00003395 58                  <1> 	pop	eax ; E-FLAGS
  2135 00003396 58                  <1> 	pop	eax ; esp
  2136 00003397 6658                <1> 	pop	ax ; ss (KDATA)
  2137                              <1> 	;
  2138 00003399 31C0                <1> 	xor	eax, eax ; 0
  2139 0000339B A3[4F6F0000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2140                              <1> 	;
  2141                              <1> 	; 02/07/2015
  2142                              <1> 	; [u.pgdir ] = [k_page_dir]
  2143                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2144                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2145                              <1> init_exec:
  2146                              <1> 	; 13/03/2013
  2147                              <1> 	; 24/07/2013
  2148 000033A0 BB[C7330000]        <1> 	mov	ebx, init_file
  2149 000033A5 B9[BF330000]        <1> 	mov	ecx, init_argp
  2150                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2151                              <1> 	; ECX contains address of argument list pointer
  2152                              <1> 	;
  2153                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2154                              <1> 			      ; 0 = executing a system call
  2155                              <1> 	sys	_exec  ; execute file
  2089                              <2> 
  2090                              <2> 
  2091 000033AA B80B000000          <2>  mov eax, %1
  2092                              <2>  %if %0 >= 2
  2093                              <2>  mov ebx, %2
  2094                              <2>  %if %0 >= 3
  2095                              <2>  mov ecx, %3
  2096                              <2>  %if %0 = 4
  2097                              <2>  mov edx, %4
  2098                              <2>  %endif
  2099                              <2>  %endif
  2100                              <2>  %endif
  2101 000033AF CD30                <2>  int 30h
  2156 000033B1 731E                <1> 	jnc	short panic
  2157                              <1> 	;
  2158 000033B3 BE[5A680000]        <1> 	mov	esi, etc_init_err_msg
  2159 000033B8 E837000000          <1> 	call 	print_msg
  2160 000033BD EB1C                <1> 	jmp	short key_to_reboot
  2161                              <1> 
  2162                              <1> ;align 4
  2163                              <1> init_argp:
  2164 000033BF [C7330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2165                              <1> init_file:
  2166                              <1> 	; 24/08/2015
  2167 000033C7 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2167 000033D0 00                  <1>
  2168                              <1> panic:
  2169                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2170                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2171 000033D1 BE[3F680000]        <1> 	mov 	esi, panic_msg
  2172 000033D6 E819000000          <1> 	call 	print_msg
  2173                              <1> key_to_reboot:
  2174                              <1> 	; 15/11/2015
  2175 000033DB E8DA2B0000          <1> 	call 	getch 
  2176                              <1> 		; wait for a character from the current tty
  2177                              <1> 	;
  2178 000033E0 B00A                <1> 	mov	al, 0Ah
  2179 000033E2 8A1D[766B0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2180 000033E8 B407                <1> 	mov	ah, 07h ; Black background, 
  2181                              <1> 			; light gray forecolor
  2182 000033EA E804E0FFFF          <1> 	call 	write_tty
  2183 000033EF E99FDCFFFF          <1> 	jmp	cpu_reset 
  2184                              <1> 
  2185                              <1> print_msg:
  2186                              <1> 	; 01/07/2015
  2187                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2188                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2189                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2190                              <1> 	;
  2191                              <1> 	;
  2192 000033F4 AC                  <1> 	lodsb
  2193                              <1> pmsg1:
  2194 000033F5 56                  <1> 	push 	esi
  2195 000033F6 0FB61D[766B0000]    <1> 	movzx	ebx, byte [ptty]
  2196 000033FD B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2197 000033FF E8EFDFFFFF          <1> 	call 	write_tty
  2198 00003404 5E                  <1> 	pop	esi
  2199 00003405 AC                  <1> 	lodsb
  2200 00003406 20C0                <1> 	and 	al, al
  2201 00003408 75EB                <1> 	jnz 	short pmsg1
  2202 0000340A C3                  <1> 	retn
  2203                              <1> 	
  2204                              <1> ctrlbrk:
  2205                              <1> 	; 04/02/2022
  2206                              <1> 	; 01/02/2022
  2207                              <1> 	; 12/11/2015
  2208                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2209                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2210                              <1> 	;
  2211                              <1> 	; INT 1Bh (control+break) handler
  2212                              <1> 	;
  2213                              <1>       	; Retro Unix 8086 v1 feature only!
  2214                              <1>       	;
  2215 0000340B 66833D[366F0000]00  <1> 	cmp 	word [u.intr], 0
  2216 00003413 764B                <1> 	jna 	short cbrk4
  2217                              <1> cbrk0:
  2218                              <1> 	; 12/11/2015
  2219                              <1> 	; 06/12/2013
  2220 00003415 66833D[386F0000]00  <1> 	cmp 	word [u.quit], 0
  2221 0000341D 7441                <1> 	jz	short cbrk4
  2222                              <1> 	;
  2223                              <1> 	; 20/09/2013	
  2224                              <1> 	;push 	ax
  2225                              <1> 	; 01/02/2022
  2226 0000341F 50                  <1> 	push	eax
  2227                              <1> 
  2228                              <1> 	; 04/02/2022
  2229                              <1> 	; (repetitive ctrl+brk check) 
  2230 00003420 66A1[386F0000]      <1> 	mov	ax, [u.quit]
  2231 00003426 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2232 00003428 7435                <1> 	jz	short cbrk3
  2233                              <1> 
  2234                              <1> 	; 20/09/2013
  2235 0000342A A0[766B0000]        <1> 	mov	al, [ptty]
  2236                              <1> 	;
  2237                              <1> 	; 12/11/2015
  2238                              <1> 	;
  2239                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2240                              <1> 	; or ctrl+break from console (pseudo) tty
  2241                              <1> 	; (!redirection!)
  2242                              <1> 	;
  2243 0000342F 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2244 00003431 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2245                              <1> 	;	
  2246                              <1> 	; Serial port interrupt handler sets [ptty]
  2247                              <1> 	; to the port's tty number (as temporary).
  2248                              <1> 	;
  2249                              <1> 	; If active process is using a stdin or 
  2250                              <1> 	; stdout redirection (by the shell),
  2251                              <1>         ; console tty keyboard must be available
  2252                              <1> 	; to terminate running process,
  2253                              <1> 	; in order to prevent a deadlock. 
  2254                              <1> 	;
  2255 00003433 52                  <1> 	push	edx
  2256 00003434 0FB615[416F0000]    <1> 	movzx	edx, byte [u.uno]
  2257 0000343B 3A82[556C0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2258 00003441 5A                  <1> 	pop	edx
  2259 00003442 7412                <1> 	je	short cbrk2
  2260                              <1> cbrk1:
  2261 00003444 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2262                              <1> 	; 06/12/2013
  2263 00003446 3A05[286F0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2264 0000344C 7408                <1> 	je	short cbrk2	
  2265 0000344E 3A05[296F0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2266 00003454 7509                <1> 	jne	short cbrk3	
  2267                              <1> cbrk2:
  2268                              <1> 	;; 06/12/2013
  2269                              <1> 	;mov	ax, [u.quit]
  2270                              <1> 	;and	ax, ax
  2271                              <1> 	;jz	short cbrk3
  2272                              <1> 	;
  2273                              <1> 	;xor	ax, ax ; 0
  2274                              <1> 	;dec	ax
  2275                              <1> 	; 01/02/2022
  2276 00003456 31C0                <1> 	xor	eax, eax ; 0
  2277 00003458 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2278                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2279 00003459 66A3[386F0000]      <1> 	mov	[u.quit], ax
  2280                              <1> cbrk3:
  2281                              <1> 	;pop	ax
  2282                              <1> 	; 01/02/2022
  2283 0000345F 58                  <1> 	pop	eax
  2284                              <1> cbrk4:
  2285 00003460 C3                  <1> 	retn
  2286                              <1> 
  2287                              <1> com2_int:
  2288                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2289                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2290                              <1> 	; 07/11/2015 
  2291                              <1> 	; 24/10/2015
  2292                              <1> 	; 23/10/2015
  2293                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2294                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2295                              <1> 	; < serial port 2 interrupt handler >
  2296                              <1> 	;
  2297 00003461 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2298                              <1> 	;;push	eax
  2299                              <1> 	; 08/01/2022
  2300 00003464 29C0                <1> 	sub	eax, eax
  2301 00003466 B009                <1> 	mov	al, 9
  2302                              <1> 	;mov	ax, 9
  2303 00003468 EB07                <1> 	jmp	short comm_int
  2304                              <1> com1_int:
  2305                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2306                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2307                              <1> 	; 07/11/2015
  2308                              <1> 	; 24/10/2015
  2309 0000346A 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2310                              <1> 	; 23/10/2015
  2311                              <1> 	;push	eax
  2312                              <1> 	; 08/01/2022
  2313 0000346D 29C0                <1> 	sub	eax, eax
  2314 0000346F B008                <1> 	mov	al, 8
  2315                              <1> 	;mov	ax, 8
  2316                              <1> comm_int:
  2317                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2318                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2319                              <1> 	; 20/11/2015
  2320                              <1> 	; 18/11/2015
  2321                              <1> 	; 17/11/2015
  2322                              <1> 	; 16/11/2015
  2323                              <1> 	; 09/11/2015
  2324                              <1> 	; 08/11/2015
  2325                              <1> 	; 07/11/2015
  2326                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2327                              <1> 	; 01/11/2015
  2328                              <1> 	; 26/10/2015
  2329                              <1> 	; 23/10/2015
  2330 00003471 53                  <1> 	push	ebx
  2331 00003472 56                  <1> 	push	esi
  2332 00003473 57                  <1> 	push	edi
  2333 00003474 1E                  <1> 	push 	ds
  2334 00003475 06                  <1> 	push 	es
  2335                              <1> 	; 18/11/2015
  2336 00003476 0F20DB              <1> 	mov	ebx, cr3
  2337 00003479 53                  <1> 	push	ebx ; ****
  2338                              <1> 	;
  2339 0000347A 51                  <1> 	push	ecx ; ***
  2340 0000347B 52                  <1> 	push	edx ; **
  2341                              <1> 	;
  2342 0000347C BB10000000          <1> 	mov	ebx, KDATA
  2343 00003481 8EDB                <1> 	mov	ds, bx
  2344 00003483 8EC3                <1> 	mov	es, bx
  2345                              <1> 	;
  2346 00003485 8B0D[486B0000]      <1> 	mov	ecx, [k_page_dir]
  2347 0000348B 0F22D9              <1> 	mov	cr3, ecx
  2348                              <1> 	; 20/11/2015
  2349                              <1> 	; Interrupt identification register
  2350 0000348E 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2351                              <1> 	;
  2352 00003492 3C08                <1> 	cmp 	al, 8 
  2353 00003494 7702                <1> 	ja 	short com_i0
  2354                              <1> 	;
  2355                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2356                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2357                              <1> 	; 20/11/2015
  2358                              <1> 	; 17/11/2015
  2359                              <1> 	; 16/11/2015
  2360                              <1> 	; 15/11/2015
  2361                              <1> 	; 24/10/2015
  2362                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2363                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2364                              <1> 	; < serial port 1 interrupt handler >
  2365                              <1> 	;
  2366 00003496 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2367                              <1> com_i0:
  2368                              <1> 	;push	eax ; *
  2369                              <1> 	; 07/11/2015
  2370 00003498 A2[B66B0000]        <1> 	mov 	byte [ccomport], al
  2371                              <1> 	; 09/11/2015
  2372                              <1> 	;movzx	ebx, ax ; 8 or 9
  2373                              <1> 	; 08/01/2022
  2374 0000349D 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2375                              <1> 	; 17/11/2015
  2376                              <1>  	; reset request for response status
  2377 0000349F 88A3[AC6B0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2378                              <1> 	;
  2379                              <1> 	; 20/11/2015
  2380 000034A5 EC                  <1> 	in	al, dx		; read interrupt id. register
  2381 000034A6 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2382 000034A8 2404                <1> 	and	al, 4		; received data available?	
  2383 000034AA 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2384                              <1> 	;
  2385                              <1> 	; 20/11/2015
  2386 000034AC 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2387 000034AF EC                  <1> 	in	al, dx     	; read character
  2388                              <1> 	;JMP	$+2	   	; I/O DELAY
  2389                              <1> 	; 08/11/2015
  2390                              <1> 	; 07/11/2015
  2391 000034B0 89DE                <1> 	mov	esi, ebx 
  2392 000034B2 89DF                <1> 	mov	edi, ebx
  2393 000034B4 81C6[B06B0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2394 000034BA 81C7[B26B0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2395 000034C0 8806                <1> 	mov	[esi], al ; received char (current char)
  2396                              <1> 	; query
  2397 000034C2 20C0                <1> 	and	al, al
  2398 000034C4 7527                <1> 	jnz	short com_i2
  2399                              <1>    	; response
  2400                              <1> 	; 17/11/2015
  2401                              <1> 	; set request for response status
  2402 000034C6 FE83[AC6B0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2403                              <1> 	;
  2404 000034CC 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2405 000034D0 EC                  <1> 	in	al, dx	   	; read line status register 
  2406 000034D1 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2407 000034D3 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2408 000034D5 7445                <1> 	jz	short com_eoi 	; no
  2409 000034D7 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2410 000034D9 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2411 000034DD EE                  <1> 	out	dx, al	   	; send on serial port
  2412                              <1> 	; 17/11/2015
  2413 000034DE 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2414 000034E1 7502                <1> 	jne 	short com_i1    ; no
  2415 000034E3 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2416                              <1> com_i1:
  2417                              <1> 	; 17/11/2015
  2418                              <1> 	; reset request for response status (again)
  2419 000034E5 FE8B[AC6B0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2420 000034EB EB2F                <1> 	jmp	short com_eoi
  2421                              <1> com_i2:	
  2422                              <1> 	; 08/11/2015
  2423 000034ED 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2424 000034EF 7417                <1> 	je	short com_i3	; (check for response signal)
  2425                              <1> 	; 07/11/2015
  2426 000034F1 3C04                <1> 	cmp	al, 04h	; EOT
  2427 000034F3 751C                <1> 	jne	short com_i4	
  2428                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2429                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2430                              <1> 	; 08/11/2015
  2431                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2432 000034F5 861D[766B0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2433 000034FB E80BFFFFFF          <1> 	call 	ctrlbrk
  2434 00003500 861D[766B0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2435                              <1> 	;mov	al, 04h ; EOT
  2436                              <1> 	; 08/11/2015
  2437 00003506 EB09                <1> 	jmp	short com_i4	
  2438                              <1> com_i3:
  2439                              <1> 	; 08/11/2015
  2440                              <1> 	; If 0FFh has been received just after a query
  2441                              <1> 	; (schar, ZERO), it is a response signal.
  2442                              <1> 	; 17/11/2015
  2443 00003508 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2444 0000350B 7704                <1> 	ja	short com_i4 ; no
  2445                              <1> 	; reset query status (schar)
  2446 0000350D 8807                <1> 	mov	[edi], al ; 0FFh
  2447 0000350F FEC0                <1> 	inc	al ; 0
  2448                              <1> com_i4:
  2449                              <1> 	; 27/07/2014
  2450                              <1> 	; 09/07/2014
  2451 00003511 D0E3                <1> 	shl	bl, 1	
  2452 00003513 81C3[786B0000]      <1> 	add	ebx, ttychr
  2453                              <1> 	; 23/07/2014 (always overwrite)
  2454                              <1> 	;;cmp	word [ebx], 0
  2455                              <1> 	;;ja	short com_eoi
  2456                              <1> 	;
  2457 00003519 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2458                              <1> 			    ; scan code = 0
  2459                              <1> com_eoi:
  2460                              <1> 	;mov	al, 20h
  2461                              <1> 	;out	20h, al	   ; end of interrupt
  2462                              <1> 	;
  2463                              <1> 	; 07/11/2015
  2464                              <1>       	;pop	eax ; *
  2465 0000351C A0[B66B0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2466                              <1> 	; al = tty number (8 or 9)
  2467 00003521 E8B01A0000          <1>         call	wakeup
  2468                              <1> com_iret:
  2469                              <1> 	; 23/10/2015
  2470 00003526 5A                  <1> 	pop	edx ; **
  2471 00003527 59                  <1> 	pop	ecx ; ***
  2472                              <1> 	; 18/11/2015
  2473                              <1> 	;pop	eax ; ****
  2474                              <1> 	;mov	cr3, eax
  2475                              <1> 	;jmp	iiret
  2476 00003528 E99DD4FFFF          <1> 	jmp	iiretp
  2477                              <1> 
  2478                              <1> ;hfgchr:
  2479                              <1> ;	db '0123456789ABCDEF?*'
  2480                              <1> ;	db 0
  2481                              <1> 
  2482                              <1> ;iiretp: ; 01/09/2015
  2483                              <1> ;	; 28/08/2015
  2484                              <1> ;	pop	eax ; (*) page directory
  2485                              <1> ;	mov	cr3, eax
  2486                              <1> ;iiret:
  2487                              <1> ;	; 22/08/2014
  2488                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2489                              <1> ;	out	20h, al	; 8259 PORT
  2490                              <1> ;	;
  2491                              <1> ;	pop	es
  2492                              <1> ;	pop	ds
  2493                              <1> ;	pop	edi
  2494                              <1> ;	pop	esi
  2495                              <1> ;	pop	ebx ; 29/08/2014
  2496                              <1> ;	pop 	eax
  2497                              <1> ;	iretd
  2498                              <1> 
  2499                              <1> sp_init:
  2500                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2501                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2502                              <1> 	; 07/11/2015
  2503                              <1> 	; 29/10/2015
  2504                              <1> 	; 26/10/2015
  2505                              <1> 	; 23/10/2015
  2506                              <1> 	; 29/06/2015
  2507                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2508                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2509                              <1> 	; Initialization of Serial Port Communication Parameters
  2510                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2511                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2512                              <1> 	;
  2513                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2514                              <1> 	;
  2515                              <1> 	; INPUT:  (29/06/2015)
  2516                              <1> 	;	AL = 0 for COM1
  2517                              <1> 	;	     1 for COM2
  2518                              <1> 	;	AH = Communication parameters	
  2519                              <1> 	;
  2520                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2521                              <1> 	;	Bit	4	3	2	1	0
  2522                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2523                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2524                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2525                              <1> 	;		11 = even
  2526                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2527                              <1> 	;		Retro UNIX 386 v1 feature only !
  2528                              <1> 	;	Bit	7    6    5  | Baud rate
  2529                              <1> 	;		------------------------
  2530                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2531                              <1> 	;		0    0    1  | 9600 (12)
  2532                              <1> 	;		0    1    0  | 19200 (6) 
  2533                              <1> 	;		0    1	  1  | 38400 (3) 
  2534                              <1> 	;		1    0	  0  | 14400 (8)
  2535                              <1> 	;		1    0	  1  | 28800 (4)
  2536                              <1> 	;		1    1    0  | 57600 (2)
  2537                              <1> 	;		1    1    1  | 115200 (1) 	
  2538                              <1> 	
  2539                              <1> 	; References:	
  2540                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2541                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2542                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2543                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2544                              <1> 	;
  2545                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2546                              <1> 	;
  2547 0000352D BB[B26B0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2548 00003532 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2549                              <1> 	; 29/10/2015
  2550 00003536 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2551 0000353A E84F000000          <1> 	call	sp_i3	; call A4	
  2552 0000353F A880                <1> 	test	al, 80h
  2553 00003541 740E                <1> 	jz	short sp_i0 ; OK..
  2554                              <1> 		; Error !
  2555                              <1> 	;mov	dx, 3F8h
  2556 00003543 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2557                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2558                              <1> 	; 08/01/2022
  2559 00003546 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2560 00003548 E841000000          <1> 	call	sp_i3	; call A4	
  2561 0000354D A880                <1> 	test	al, 80h
  2562 0000354F 7508                <1> 	jnz	short sp_i1
  2563                              <1> sp_i0:
  2564                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2565                              <1>         ; (INT 14h initialization code disables interrupts.)
  2566                              <1> 	;
  2567 00003551 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2568 00003554 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2569                              <1> sp_i1:
  2570 00003559 43                  <1> 	inc	ebx
  2571 0000355A 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2572                              <1> 	; 29/10/2015
  2573                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2574                              <1> 	; 08/01/2022
  2575 0000355E B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2576 00003560 E829000000          <1> 	call	sp_i3	; call A4	
  2577 00003565 A880                <1> 	test	al, 80h
  2578 00003567 740E                <1> 	jz	short sp_i2 ; OK..
  2579                              <1> 		; Error !
  2580                              <1> 	;mov	dx, 2F8h
  2581 00003569 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2582                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2583                              <1> 	; 08/01/2022
  2584 0000356C B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2585 0000356E E81B000000          <1> 	call	sp_i3	; call A4	
  2586 00003573 A880                <1> 	test	al, 80h
  2587 00003575 7516                <1> 	jnz	short sp_i7
  2588                              <1> sp_i2:
  2589 00003577 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2590                              <1> sp_i6:
  2591                              <1> 	;; COM2 - enabling IRQ 3
  2592                              <1> 	; 08/01/2022
  2593 0000357A B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2594                              <1> 	; 07/11/2015
  2595                              <1> 	; 26/10/2015
  2596                              <1> 	;pushf
  2597                              <1> 	;cli
  2598                              <1> 	;;
  2599                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2600                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2601                              <1> 	;in	al, dx 	   		; read register
  2602                              <1> 	;JMP	$+2	   		; I/O DELAY
  2603                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2604                              <1> 	;out	dx, al     		; write back to register
  2605                              <1> 	;JMP	$+2	   		; I/O DELAY
  2606                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2607                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2608                              <1> 	;in	al, dx     		; read register
  2609                              <1> 	;JMP	$+2	   		; I/O DELAY
  2610                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2611                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2612                              <1> 	;out	dx, al 	   		; write back to register
  2613                              <1> 	;JMP	$+2        		; I/O DELAY
  2614                              <1> 	;in	al, 21h    		; read interrupt mask register
  2615                              <1> 	;JMP	$+2	   		; I/O DELAY
  2616                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2617                              <1> 	;out	21h, al    		; write back to register
  2618                              <1> 	;
  2619                              <1> 	; 08/01/2022
  2620 0000357C 9C                  <1> 	pushf
  2621 0000357D E8AA000000          <1> 	call	sp_i8
  2622                              <1> 	; 23/10/2015
  2623 00003582 B8[61340000]        <1> 	mov 	eax, com2_int
  2624 00003587 A3[203A0000]        <1> 	mov	[com2_irq3], eax
  2625                              <1> 	; 26/10/2015
  2626 0000358C 9D                  <1> 	popf	
  2627                              <1> sp_i7:
  2628 0000358D C3                  <1> 	retn
  2629                              <1> 
  2630                              <1> sp_i3:
  2631                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2632                              <1> 	; 28/10/2015
  2633 0000358E FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2634 00003590 B000                <1> 	mov	al, 0
  2635 00003592 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2636 00003593 EB00                <1> 	JMP	$+2			; I/O DELAY
  2637 00003595 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2638 00003598 B080                <1> 	mov	al, 80h			
  2639 0000359A EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2640                              <1> 	;-----	SET BAUD RATE DIVISOR
  2641                              <1> 	; 26/10/2015
  2642 0000359B 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2643                              <1> 					; of the divisor value
  2644 0000359E 88C8                <1> 	mov	al, cl	; 1
  2645 000035A0 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2646                              <1> 					; 2 = 57600 baud
  2647                              <1> 					; 3 = 38400 baud
  2648                              <1> 					; 6 = 19200 baud
  2649                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2650 000035A1 EB00                <1> 	JMP	$+2			; I/O DELAY
  2651 000035A3 28C0                <1> 	sub	al, al
  2652 000035A5 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2653                              <1> 					; of the divisor value
  2654 000035A7 EE                  <1> 	out	dx, al ; 0
  2655 000035A8 EB00                <1> 	JMP	$+2			; I/O DELAY
  2656                              <1> 	;	
  2657 000035AA 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2658                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2659 000035AC 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2660 000035AF EE                  <1> 	out	dx, al			
  2661 000035B0 EB00                <1> 	JMP	$+2			; I/O DELAY
  2662                              <1> 	; 29/10/2015
  2663 000035B2 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2664 000035B4 30C0                <1> 	xor	al, al			; 0
  2665 000035B6 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2666 000035B7 EB00                <1> 	JMP	$+2	
  2667                              <1> sp_i4:
  2668                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2669                              <1> 	; 29/06/2015 (line status after modem status)
  2670 000035B9 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2671                              <1> sp_i4s:
  2672 000035BC EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2673 000035BD EB00                <1> 	JMP	$+2			; I/O DELAY
  2674 000035BF 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2675 000035C1 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2676                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2677 000035C3 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2678                              <1> 	; AL = Line status, AH = Modem status
  2679 000035C4 C3                  <1> 	retn
  2680                              <1> 
  2681                              <1> sp_status:
  2682                              <1> 	; 29/06/2015
  2683                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2684                              <1> 	; Get serial port status
  2685 000035C5 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2686 000035C9 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2687                              <1> 					; dx = 2FEh for COM2
  2688 000035CB EBEF                <1> 	jmp	short sp_i4s
  2689                              <1> 
  2690                              <1> sp_setp: ; Set serial port communication parameters
  2691                              <1> 	; 04/02/2022 
  2692                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2693                              <1> 	; 08/01/2022
  2694                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2695                              <1> 	; 07/11/2015
  2696                              <1> 	; 29/10/2015
  2697                              <1> 	; 29/06/2015
  2698                              <1> 	; Retro UNIX 386 v1 feature only !	
  2699                              <1> 	;
  2700                              <1> 	; INPUT:
  2701                              <1> 	;	AL = 0 for COM1
  2702                              <1> 	;	     1 for COM2
  2703                              <1> 	;	AH = Communication parameters (*)
  2704                              <1> 	; OUTPUT:
  2705                              <1> 	;	CL = Line status
  2706                              <1> 	;	CH = Modem status
  2707                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2708                              <1> 	;		 'invalid parameter !' 
  2709                              <1> 	;		 	 or
  2710                              <1> 	;		 'device not ready !' error
  2711                              <1> 	;	
  2712                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2713                              <1> 	;	Bit	4	3	2	1	0
  2714                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2715                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2716                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2717                              <1> 	;		11 = even
  2718                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2719                              <1> 	;		Retro UNIX 386 v1 feature only !
  2720                              <1> 	;	Bit	7    6    5  | Baud rate
  2721                              <1> 	;		------------------------
  2722                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2723                              <1> 	;		0    0    1  | 9600 (12)
  2724                              <1> 	;		0    1    0  | 19200 (6) 
  2725                              <1> 	;		0    1	  1  | 38400 (3) 
  2726                              <1> 	;		1    0	  0  | 14400 (8)
  2727                              <1> 	;		1    0	  1  | 28800 (4)
  2728                              <1> 	;		1    1    0  | 57600 (2)
  2729                              <1> 	;		1    1    1  | 115200 (1) 
  2730                              <1> 	;
  2731                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2732                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2733                              <1> 	;
  2734                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2735                              <1> 	;
  2736 000035CD 66BAF803            <1> 	mov	dx, 3F8h
  2737 000035D1 BB[B26B0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2738 000035D6 3C01                <1> 	cmp	al, 1
  2739 000035D8 7770                <1> 	ja 	short sp_invp_err
  2740 000035DA 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2741 000035DC FECE                <1> 	dec	dh ; 2F8h
  2742 000035DE 43                  <1> 	inc	ebx ; COM2 control byte offset
  2743                              <1> sp_setp1:
  2744                              <1> 	; 29/10/2015
  2745 000035DF 8823                <1> 	mov	[ebx], ah
  2746 000035E1 0FB6CC              <1> 	movzx 	ecx, ah
  2747 000035E4 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2748 000035E7 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2749 000035EA 8A81[59360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2750 000035F0 6689C1              <1> 	mov	cx, ax
  2751 000035F3 E896FFFFFF          <1> 	call	sp_i3
  2752 000035F8 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2753 000035FB A880                <1> 	test	al, 80h
  2754 000035FD 740F                <1> 	jz	short sp_setp2
  2755 000035FF C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2756                              <1> stp_dnr_err:
  2757 00003602 C705[476F0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2757 0000360A 0000                <1>
  2758                              <1> 	; CL = Line status, CH = Modem status
  2759 0000360C F9                  <1> 	stc
  2760 0000360D C3                  <1> 	retn
  2761                              <1> sp_setp2:
  2762 0000360E 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2763                              <1>         ;jna	sp_i6
  2764                              <1> 		      ; COM1 (3F?h)
  2765                              <1> 	; 24/12/2021
  2766 00003611 7705                <1> 	ja	short sp_i5
  2767 00003613 E962FFFFFF          <1> 	jmp	sp_i6
  2768                              <1> sp_i5: 
  2769                              <1> 	; 08/01/2022
  2770 00003618 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2771                              <1> 	; 07/11/2015
  2772                              <1> 	; 26/10/2015
  2773                              <1> 	; 29/06/2015
  2774                              <1> 	;
  2775                              <1> 	;; COM1 - enabling IRQ 4
  2776                              <1> 	;pushf
  2777                              <1> 	;cli
  2778                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2779                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2780                              <1> 	;in	al, dx 	   		; read register
  2781                              <1> 	;JMP	$+2			; I/O DELAY
  2782                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2783                              <1> 	;out	dx, al     		; write back to register
  2784                              <1> 	;JMP	$+2			; I/O DELAY
  2785                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2786                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2787                              <1> 	;in	al, dx     		; read register
  2788                              <1> 	;JMP	$+2			; I/O DELAY
  2789                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2790                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2791                              <1> 	;out	dx, al 	   		; write back to register
  2792                              <1> 	;JMP	$+2        		; I/O DELAY
  2793                              <1> 	;in	al, 21h    		; read interrupt mask register
  2794                              <1> 	;JMP	$+2			; I/O DELAY
  2795                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2796                              <1> 	;out	21h, al    		; write back to register
  2797                              <1> 	;
  2798                              <1> 	; 08/01/2022
  2799 0000361A 9C                  <1> 	pushf
  2800 0000361B E80C000000          <1> 	call	sp_i8
  2801                              <1> 	; 23/10/2015
  2802 00003620 B8[6A340000]        <1> 	mov 	eax, com1_int
  2803 00003625 A3[1C3A0000]        <1> 	mov	[com1_irq4], eax
  2804                              <1> 	; 26/10/2015
  2805 0000362A 9D                  <1> 	popf
  2806 0000362B C3                  <1> 	retn
  2807                              <1> 
  2808                              <1> sp_i8:
  2809                              <1> 	; 08/01/2022
  2810                              <1> 	;pushf
  2811 0000362C FA                  <1> 	cli
  2812                              <1> 	;
  2813                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2814 0000362D B2FC                <1> 	mov	dl, 0FCh
  2815 0000362F EC                  <1> 	in	al, dx 	   		; read register
  2816 00003630 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2817 00003632 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2818 00003634 EE                  <1> 	out	dx, al     		; write back to register
  2819 00003635 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2820                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2821 00003637 B2F9                <1> 	mov	dl, 0F9h
  2822 00003639 EC                  <1> 	in	al, dx     		; read register
  2823 0000363A EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2824                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2825 0000363C 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2826 0000363E EE                  <1> 	out	dx, al 	   		; write back to register
  2827 0000363F EB00                <1> 	JMP	$+2        		; I/O DELAY
  2828 00003641 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2829 00003643 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2830                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2831 00003645 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2832 00003647 E621                <1> 	out	21h, al    		; write back to register
  2833                              <1> 	;
  2834                              <1> 	;popf	
  2835 00003649 C3                  <1> 	retn
  2836                              <1> 
  2837                              <1> sp_invp_err:
  2838 0000364A C705[476F0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2838 00003652 0000                <1>
  2839 00003654 31C9                <1> 	xor	ecx, ecx
  2840 00003656 49                  <1> 	dec	ecx ; 0FFFFh
  2841 00003657 F9                  <1> 	stc
  2842 00003658 C3                  <1> 	retn
  2843                              <1> 
  2844                              <1> ; 29/10/2015
  2845                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2846 00003659 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2847                              <1> 
  2848                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2849                              <1> epoch:
  2850                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2851                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2852                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2853                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2854                              <1> 	; 'epoch' procedure prototype: 
  2855                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2856                              <1> 	; 14/11/2012
  2857                              <1> 	; unixboot.asm (boot file configuration)
  2858                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2859                              <1> 	; 21/7/2012
  2860                              <1> 	; 15/7/2012
  2861                              <1> 	; 14/7/2012		
  2862                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2863                              <1> 	; compute current date and time as UNIX Epoch/Time
  2864                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2865                              <1> 	;
  2866                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2867                              <1> 	;
  2868 00003660 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2869 00003665 86E9                <1>         xchg 	ch,cl
  2870 00003667 66890D[B4680000]    <1>         mov 	[hour], cx
  2871 0000366E 86F2                <1>         xchg 	dh,dl
  2872 00003670 668915[B8680000]    <1>         mov 	[second], dx
  2873                              <1> 	;
  2874 00003677 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2875 0000367C 86E9                <1>         xchg 	ch,cl
  2876 0000367E 66890D[AE680000]    <1>         mov 	[year], cx
  2877 00003685 86F2                <1>         xchg 	dh,dl
  2878 00003687 668915[B0680000]    <1>         mov 	[month], dx
  2879                              <1> 	;
  2880 0000368E 66B93030            <1> 	mov 	cx, 3030h
  2881                              <1> 	;
  2882 00003692 A0[B4680000]        <1> 	mov 	al, [hour] ; Hour
  2883                              <1>         	; AL <= BCD number)
  2884 00003697 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2885                              <1> 					; AH = AL / 10h
  2886                              <1> 					; AL = AL MOD 10h
  2887 00003699 D50A                <1>         aad 	; AX= AH*10+AL
  2888 0000369B A2[B4680000]        <1> 	mov 	[hour], al
  2889 000036A0 A0[B5680000]        <1> 	mov 	al, [hour+1] ; Minute
  2890                              <1>         	; AL <= BCD number)
  2891 000036A5 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2892                              <1> 					; AH = AL / 10h
  2893                              <1> 					; AL = AL MOD 10h
  2894 000036A7 D50A                <1>         aad 	; AX= AH*10+AL
  2895 000036A9 A2[B6680000]        <1> 	mov 	[minute], al
  2896 000036AE A0[B8680000]        <1> 	mov 	al, [second] ; Second
  2897                              <1>         	; AL <= BCD number)
  2898 000036B3 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2899                              <1> 					; AH = AL / 10h
  2900                              <1> 					; AL = AL MOD 10h
  2901 000036B5 D50A                <1>         aad 	; AX= AH*10+AL
  2902 000036B7 A2[B8680000]        <1> 	mov 	[second], al
  2903 000036BC 66A1[AE680000]      <1> 	mov 	ax, [year] ; Year (century)
  2904                              <1>  	;push 	ax
  2905                              <1> 	; 08/01/2022
  2906 000036C2 50                  <1> 	push	eax
  2907                              <1> 	   	; AL <= BCD number)
  2908 000036C3 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2909                              <1> 					; AH = AL / 10h
  2910                              <1> 					; AL = AL MOD 10h
  2911 000036C5 D50A                <1>         aad 	; AX= AH*10+AL
  2912 000036C7 B464                <1> 	mov 	ah, 100
  2913 000036C9 F6E4                <1> 	mul 	ah
  2914 000036CB 66A3[AE680000]      <1> 	mov 	[year], ax
  2915                              <1> 	;pop	ax
  2916                              <1> 	; 08/01/2022
  2917 000036D1 58                  <1> 	pop	eax
  2918 000036D2 88E0                <1> 	mov	al, ah
  2919                              <1>         	; AL <= BCD number)
  2920 000036D4 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2921                              <1> 					; AH = AL / 10h
  2922                              <1> 					; AL = AL MOD 10h
  2923 000036D6 D50A                <1>         aad 	; AX= AH*10+AL
  2924 000036D8 660105[AE680000]    <1> 	add 	[year], ax
  2925 000036DF A0[B0680000]        <1> 	mov 	al, [month] ; Month
  2926                              <1>            	; AL <= BCD number)
  2927 000036E4 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2928                              <1> 					; AH = AL / 10h
  2929                              <1> 					; AL = AL MOD 10h
  2930 000036E6 D50A                <1>         aad 	; AX= AH*10+AL
  2931 000036E8 A2[B0680000]        <1> 	mov 	[month], al	
  2932 000036ED A0[B1680000]        <1>         mov     al, [month+1]      	; Day
  2933                              <1>            	; AL <= BCD number)
  2934 000036F2 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2935                              <1> 					; AH = AL / 10h
  2936                              <1> 					; AL = AL MOD 10h
  2937 000036F4 D50A                <1>         aad 	; AX= AH*10+AL
  2938 000036F6 A2[B2680000]        <1>         mov     [day], al
  2939                              <1> 	
  2940                              <1> convert_to_epoch:
  2941                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  2942                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  2943                              <1> 	;
  2944                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  2945                              <1> 	;
  2946                              <1> 	; Derived from DALLAS Semiconductor
  2947                              <1> 	; Application Note 31 (DS1602/DS1603)
  2948                              <1> 	; 6 May 1998
  2949 000036FB 29C0                <1> 	sub 	eax, eax
  2950 000036FD 66A1[AE680000]      <1> 	mov 	ax, [year]
  2951 00003703 662DB207            <1> 	sub 	ax, 1970
  2952 00003707 BA6D010000          <1> 	mov 	edx, 365
  2953 0000370C F7E2                <1> 	mul 	edx
  2954 0000370E 31DB                <1> 	xor 	ebx, ebx
  2955 00003710 8A1D[B0680000]      <1> 	mov 	bl, [month]
  2956 00003716 FECB                <1> 	dec 	bl
  2957 00003718 D0E3                <1> 	shl 	bl, 1
  2958                              <1> 	;sub	edx, edx
  2959 0000371A 668B93[BA680000]    <1> 	mov 	dx, [EBX+DMonth]
  2960 00003721 8A1D[B2680000]      <1>         mov     bl, [day]
  2961 00003727 FECB                <1> 	dec 	bl
  2962 00003729 01D0                <1> 	add 	eax, edx
  2963 0000372B 01D8                <1> 	add 	eax, ebx
  2964                              <1> 			; EAX = days since 1/1/1970
  2965 0000372D 668B15[AE680000]    <1> 	mov 	dx, [year]
  2966 00003734 6681EAB107          <1> 	sub 	dx, 1969
  2967 00003739 66D1EA              <1> 	shr 	dx, 1
  2968 0000373C 66D1EA              <1> 	shr 	dx, 1		
  2969                              <1> 		; (year-1969)/4
  2970 0000373F 01D0                <1> 	add 	eax, edx
  2971                              <1> 			; + leap days since 1/1/1970
  2972 00003741 803D[B0680000]02    <1> 	cmp 	byte [month], 2	; if past february
  2973 00003748 7610                <1> 	jna 	short cte1
  2974 0000374A 668B15[AE680000]    <1> 	mov 	dx, [year]
  2975 00003751 6683E203            <1> 	and 	dx, 3 ; year mod 4
  2976 00003755 7503                <1> 	jnz 	short cte1		
  2977                              <1> 			; and if leap year
  2978 00003757 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  2979                              <1> cte1: 			; compute seconds since 1/1/1970
  2980 0000375A BA18000000          <1> 	mov 	edx, 24
  2981 0000375F F7E2                <1> 	mul	edx
  2982 00003761 8A15[B4680000]      <1> 	mov 	dl, [hour]
  2983 00003767 01D0                <1> 	add 	eax, edx
  2984                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  2985                              <1> 	;mov	ebx, 60
  2986 00003769 B33C                <1> 	mov	bl, 60
  2987 0000376B F7E3                <1> 	mul	ebx
  2988 0000376D 8A15[B6680000]      <1> 	mov 	dl, [minute]
  2989 00003773 01D0                <1> 	add 	eax, edx
  2990                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  2991                              <1> 	;mov 	ebx, 60
  2992 00003775 F7E3                <1> 	mul	ebx
  2993 00003777 8A15[B8680000]      <1> 	mov 	dl, [second]
  2994 0000377D 01D0                <1> 	add 	eax, edx
  2995                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  2996 0000377F C3                  <1> 	retn
  2997                              <1> 
  2998                              <1> get_rtc_time:
  2999                              <1> 	; 15/03/2015
  3000                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3001                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3002                              <1> 	; INT 1Ah						:
  3003                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3004                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3005                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3006                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3007                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3008                              <1> 	;								
  3009                              <1> RTC_20: 			; GET RTC TIME
  3010 00003780 FA                  <1> 	cli
  3011 00003781 E8E7D3FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3012 00003786 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3013                              <1> 
  3014 00003788 B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3015 0000378A E8C6D3FFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3016 0000378F 88C6                <1> 	MOV	DH,AL		; SAVE
  3017 00003791 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3018 00003793 E8BDD3FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3019 00003798 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3020 0000379A 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3021 0000379C B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3022 0000379E E8B2D3FFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3023 000037A3 88C1                <1> 	MOV	CL,AL		; SAVE
  3024 000037A5 B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3025 000037A7 E8A9D3FFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3026 000037AC 88C5                <1> 	MOV	CH,AL		; SAVE
  3027 000037AE F8                  <1> 	CLC			; SET CY= 0
  3028                              <1> RTC_29:
  3029 000037AF FB                  <1> 	sti
  3030 000037B0 C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3031                              <1> 
  3032                              <1> get_rtc_date:
  3033                              <1> 	; 15/03/2015
  3034                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3035                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3036                              <1> 	; INT 1Ah						       :
  3037                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3038                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3039                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3040                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3041                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3042                              <1> 	;
  3043                              <1> RTC_40: 			; GET RTC DATE
  3044 000037B1 FA                  <1> 	cli
  3045 000037B2 E8B6D3FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3046 000037B7 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3047                              <1> 
  3048 000037B9 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3049 000037BB E895D3FFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3050 000037C0 88C2                <1> 	MOV	DL,AL		; SAVE
  3051 000037C2 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3052 000037C4 E88CD3FFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3053 000037C9 88C6                <1> 	MOV	DH,AL		; SAVE
  3054 000037CB B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3055 000037CD E883D3FFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3056 000037D2 88C1                <1> 	MOV	CL,AL		; SAVE
  3057 000037D4 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3058 000037D6 E87AD3FFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3059 000037DB 88C5                <1> 	MOV	CH,AL		; SAVE
  3060 000037DD F8                  <1> 	CLC			; SET CY=0
  3061                              <1> RTC_49:
  3062 000037DE FB                  <1> 	sti
  3063 000037DF C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3064                              <1> 
  3065                              <1> set_date_time:
  3066                              <1> convert_from_epoch:
  3067                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3068                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3069                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3070                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3071                              <1> 	;
  3072                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3073                              <1> 	;
  3074                              <1> 	; Derived from DALLAS Semiconductor
  3075                              <1> 	; Application Note 31 (DS1602/DS1603)
  3076                              <1> 	; 6 May 1998
  3077                              <1> 	;
  3078                              <1> 	; INPUT:
  3079                              <1> 	; EAX = Unix (Epoch) Time
  3080                              <1> 	;
  3081 000037E0 31D2                <1> 	xor 	edx, edx
  3082 000037E2 B93C000000          <1> 	mov 	ecx, 60
  3083 000037E7 F7F1                <1> 	div	ecx
  3084                              <1> 	;mov 	[imin], eax   ; whole minutes
  3085                              <1> 			  ; since 1/1/1970
  3086 000037E9 668915[B8680000]    <1> 	mov 	[second], dx  ; leftover seconds
  3087 000037F0 29D2                <1> 	sub 	edx, edx
  3088 000037F2 F7F1                <1> 	div	ecx
  3089                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3090                              <1> 	;		      ; since 1/1/1970
  3091 000037F4 668915[B6680000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3092 000037FB 31D2                <1> 	xor	edx, edx
  3093                              <1> 	;mov 	cx, 24
  3094 000037FD B118                <1> 	mov 	cl, 24
  3095 000037FF F7F1                <1> 	div	ecx
  3096                              <1> 	;mov 	[iday], ax   ; whole days
  3097                              <1> 			     ; since 1/1/1970
  3098 00003801 668915[B4680000]    <1> 	mov 	[hour], dx   ; leftover hours
  3099 00003808 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3100                              <1> 			     ; 1/1/1968 	
  3101                              <1> 	;mov 	[iday], ax
  3102 0000380D 50                  <1> 	push 	eax
  3103 0000380E 29D2                <1> 	sub	edx, edx
  3104 00003810 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3105 00003815 F7F1                <1> 	div	ecx
  3106 00003817 59                  <1> 	pop 	ecx
  3107                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3108 00003818 6652                <1> 	push 	dx
  3109                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3110 0000381A 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3111 0000381E F5                  <1> 	cmc		     ; add this quadyr's leap day
  3112 0000381F 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3113                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3114                              <1> 	;mov 	cx, [iday]
  3115 00003822 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3116 00003823 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3117 00003825 B96D010000          <1> 	mov 	ecx, 365
  3118 0000382A 31D2                <1> 	xor	edx, edx
  3119                              <1> 	; EAX = iday-lday, EDX = 0
  3120 0000382C F7F1                <1> 	div	ecx
  3121                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3122                              <1> 	;jday = iday - (iyrs*365) - lday
  3123                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3124                              <1> 	;add	eax, 1968
  3125 0000382E 6605B007            <1> 	add 	ax, 1968     ; compute year
  3126 00003832 66A3[AE680000]      <1> 	mov 	[year], ax
  3127 00003838 6689D1              <1> 	mov 	cx, dx
  3128                              <1> 	;mov 	dx, [qday]
  3129 0000383B 665A                <1> 	pop 	dx
  3130 0000383D 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3131 00003842 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3132 00003844 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3133 00003848 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3134 00003849 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3135                              <1> cfe1:			
  3136                              <1> 	;mov 	[jday], cx
  3137 0000384D 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3138 00003851 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3139 00003855 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3140                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3141 00003859 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3142 0000385C 731D                <1> 	jnb 	short cfe3
  3143 0000385E 664B                <1> 	dec 	bx           ; month = month - 1
  3144 00003860 66D1E3              <1> 	shl 	bx, 1 
  3145 00003863 668B93[BA680000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3146 0000386A 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3147 0000386D 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3148 00003871 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3149 00003873 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3150 00003875 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3151 00003877 6642                <1> 	inc 	dx           ; mday = mday + 1
  3152 00003879 EBDE                <1> 	jmp 	short cfe2
  3153                              <1> cfe3:
  3154 0000387B 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3155 0000387D 66891D[B0680000]    <1> 	mov 	[month], bx
  3156 00003884 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3157 00003887 6641                <1> 	inc 	cx 			  
  3158 00003889 66890D[B2680000]    <1> 	mov 	[day], cx
  3159                              <1> 	
  3160                              <1> 	; eax, ebx, ecx, edx is changed at return
  3161                              <1> 	; output ->
  3162                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3163                              <1> 	
  3164                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3165                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3166                              <1> set_date:
  3167 00003890 A0[AF680000]        <1>         mov     al, [year+1]
  3168 00003895 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3169 00003897 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3170                              <1> 			     ; AL = AH * 10h + AL
  3171 00003899 88C5                <1> 	mov 	ch, al ; century (BCD)
  3172 0000389B A0[AE680000]        <1> 	mov 	al, [year]
  3173 000038A0 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3174 000038A2 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3175                              <1> 			     ; AL = AH * 10h + AL
  3176 000038A4 88C1                <1> 	mov 	cl, al ; year (BCD)
  3177 000038A6 A0[B0680000]        <1>         mov 	al, [month]
  3178 000038AB D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3179 000038AD D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3180                              <1> 			     ; AL = AH * 10h + AL
  3181 000038AF 88C6                <1> 	mov 	dh, al ; month (BCD)
  3182 000038B1 A0[B2680000]        <1> 	mov 	al, [day]
  3183 000038B6 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3184 000038B8 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3185                              <1> 			     ; AL = AH * 10h + AL
  3186 000038BA 88C6                <1> 	mov 	dh, al ; day (BCD)
  3187                              <1> 	; Set real-time clock date
  3188 000038BC E879000000          <1> 	call	set_rtc_date
  3189                              <1> set_time:
  3190                              <1>         ; Read real-time clock time 
  3191                              <1> 	; (get day light saving time bit status)
  3192 000038C1 FA                  <1>  	cli
  3193 000038C2 E8A6D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3194                              <1> 	; cf = 1 -> al = 0
  3195 000038C7 7207                <1>         jc      short stime1
  3196 000038C9 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3197 000038CB E885D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3198                              <1> stime1:
  3199 000038D0 FB                  <1> 	sti
  3200 000038D1 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3201 000038D3 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3202                              <1> 	; DL = 1 or 0 (day light saving time)
  3203                              <1> 	;	
  3204 000038D5 A0[B4680000]        <1> 	mov 	al, [hour]
  3205 000038DA D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3206 000038DC D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3207                              <1> 			     ; AL = AH * 10h + AL
  3208 000038DE 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3209 000038E0 A0[B6680000]        <1>         mov     al, [minute]
  3210 000038E5 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3211 000038E7 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3212                              <1> 			     ; AL = AH * 10h + AL
  3213 000038E9 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3214 000038EB A0[B8680000]        <1>         mov     al, [second]
  3215 000038F0 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3216 000038F2 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3217                              <1> 			     ; AL = AH * 10h + AL
  3218 000038F4 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3219                              <1> 	; Set real-time clock time
  3220                              <1>  	; call	set_rtc_time
  3221                              <1> set_rtc_time:
  3222                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3223                              <1> 	; 15/03/2015							  :
  3224                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3225                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3226                              <1> 	; INT 1Ah							  :
  3227                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3228                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3229                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3230                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3231                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3232                              <1> 	;								  :
  3233                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3234                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3235                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3236                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3237                              <1> 	;								  :
  3238                              <1> RTC_30: 			; SET RTC TIME
  3239 000038F6 FA                  <1> 	cli
  3240 000038F7 E871D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3241 000038FC 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3242 000038FE E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3243                              <1> RTC_35:
  3244 00003903 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3245 00003905 B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3246 00003907 E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3247 0000390C 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3248 0000390E B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3249 00003910 E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3250 00003915 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3251 00003917 B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3252 00003919 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3253                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3254 0000391E 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3255 00003922 E82ED2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3256 00003927 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3257 00003929 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3258 0000392B 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3259 0000392E 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3260 00003930 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3261 00003932 E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3262 00003937 F8                  <1> 	CLC			; SET CY= 0
  3263 00003938 FB                  <1> 	sti
  3264 00003939 C3                  <1> 	RETn			; RETURN WITH CY= 0
  3265                              <1> 
  3266                              <1> set_rtc_date:
  3267                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)	   :
  3268                              <1> 	; 15/03/2015						   :
  3269                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	   :
  3270                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	   :
  3271                              <1> 	; INT 1Ah						   :
  3272                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3273                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3274                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3275                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3276                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3277                              <1> 	;							   :
  3278                              <1> RTC_50: 			; SET RTC DATE
  3279 0000393A FA                  <1> 	cli
  3280 0000393B E82DD2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3281 00003940 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3282 00003942 E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3283                              <1> RTC_55:
  3284 00003947 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3285 0000394B E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3286 00003950 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3287 00003952 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3288 00003954 E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3289 00003959 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3290 0000395B B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3291 0000395D E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3292 00003962 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3293 00003964 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3294 00003966 E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3295 0000396B 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3296 0000396D B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3297 0000396F E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3298                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3299 00003974 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3300 00003978 E8D8D1FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3301 0000397D 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3302 0000397F 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3303 00003981 E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3304 00003986 F8                  <1> 	CLC			; SET CY= 0
  3305 00003987 FB                  <1> 	sti
  3306 00003988 C3                  <1> 	RETn			; RETURN CY=0
  3307                              <1> 
  3308                              <1> 	; 15/03/2015
  3309                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3310 00003989 B426                <1> 	mov	ah, 26h
  3311 0000398B B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3312 0000398D E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3313 00003992 B482                <1> 	mov	ah, 82h
  3314 00003994 B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3315 00003996 E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3316 0000399B B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3317 0000399D E8B3D1FFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3318 000039A2 B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3319                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3320                              <1> 	;RETn
  3321                              <1> 	; 12/02/2022
  3322 000039A4 E9ACD1FFFF          <1> 	jmp	CMOS_READ
  3323                              <1> 
  3324                              <1> 	; 15/03/2015
  3325                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3326                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3327 000039A9 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3328                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3329 000039AA D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3330 000039AC F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3331 000039AD D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3332 000039AF FA                  <1> 	cli			; DISABLE INTERRUPTS
  3333 000039B0 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3334 000039B2 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3335 000039B4 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3336 000039B6 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3337 000039B8 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3338 000039BA E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3339 000039BC 90                  <1> 	nop			; I/O DELAY
  3340 000039BD E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3341                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3342 000039BF 9D                  <1> 	popf	
  3343 000039C0 C3                  <1> 	RETn
  3344                              <1> 
  3345                              <1> bf_init:
  3346                              <1> 	; 14/08/2015
  3347                              <1> 	; 02/07/2015
  3348                              <1> 	; 01/07/2015
  3349                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3350                              <1> 	; Buffer (pointer) initialization !
  3351                              <1> 	; 
  3352                              <1> 	; 17/07/2013 - 24/07/2013
  3353                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3354                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3355                              <1> 	;
  3356 000039C1 BF[BA6E0000]        <1> 	mov	edi, bufp 
  3357 000039C6 B8[A87B0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3358 000039CB 29D2                <1> 	sub	edx, edx
  3359 000039CD FECA                <1> 	dec	dl
  3360 000039CF 31C9                <1> 	xor	ecx, ecx
  3361 000039D1 49                  <1> 	dec	ecx
  3362                              <1> bi0:
  3363 000039D2 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3364 000039D7 AB                  <1> 	stosd
  3365 000039D8 89C6                <1> 	mov	esi, eax
  3366 000039DA 8916                <1> 	mov	[esi], edx ; 000000FFh
  3367                              <1> 			    ; Not a valid device sign
  3368 000039DC 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3369                              <1> 		      ; Not a valid block number sign 	 	
  3370 000039DF 3D[786F0000]        <1> 	cmp	eax, buffer
  3371 000039E4 77EC                <1> 	ja	short bi0
  3372 000039E6 B8[A87B0000]        <1> 	mov	eax, sb0
  3373 000039EB AB                  <1> 	stosd
  3374 000039EC B8[B07D0000]        <1> 	mov	eax, sb1
  3375 000039F1 AB                  <1> 	stosd
  3376 000039F2 89C6                <1> 	mov	esi, eax ; offset sb1
  3377 000039F4 8916                <1> 	mov	[esi], edx ; 000000FFh
  3378                              <1> 			    ; Not a valid device sign
  3379 000039F6 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3380                              <1> 		      ; Not a valid block number sign 	 
  3381                              <1> 	; 14/08/2015
  3382                              <1> 	;call 	rdev_init
  3383                              <1> 	;retn
  3384                              <1> 
  3385                              <1> rdev_init: ; root device, super block buffer initialization
  3386                              <1> 	; 01/02/2022
  3387                              <1> 	; 14/08/2015
  3388                              <1> 	; Retro UNIX 386 v1 feature only !
  3389                              <1> 	;
  3390                              <1> 	; NOTE: Disk partitions (file systems), logical
  3391                              <1> 	; drive initialization, partition's start sector etc.
  3392                              <1> 	; will be coded here, later in 'ldrv_init'	
  3393                              <1> 
  3394 000039F9 0FB605[3A660000]    <1> 	movzx	eax, byte [boot_drv]
  3395                              <1> rdi_0:
  3396 00003A00 3C80                <1> 	cmp	al, 80h
  3397 00003A02 7202                <1> 	jb	short rdi_1
  3398 00003A04 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3399                              <1> rdi_1:
  3400 00003A06 A2[E06E0000]        <1> 	mov	[rdev], al
  3401 00003A0B BB[A87B0000]        <1>         mov	ebx, sb0 ; super block buffer
  3402 00003A10 8903                <1> 	mov 	[ebx], eax
  3403 00003A12 B001                <1> 	mov	al, 1 ; eax = 1
  3404 00003A14 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3405                              <1> 	;call 	diskio
  3406                              <1> 	;retn
  3407                              <1> 	; 01/02/2022
  3408 00003A17 E980240000          <1> 	jmp	diskio
  3409                              <1> 
  3410                              <1> ; 23/10/2015
  3411                              <1> com1_irq4:
  3412 00003A1C [243A0000]          <1> 	dd dummy_retn
  3413                              <1> com2_irq3:
  3414 00003A20 [243A0000]          <1> 	dd dummy_retn
  3415                              <1> 
  3416                              <1> dummy_retn:
  3417 00003A24 C3                  <1> 	retn
  1989                                  %include 'u1.s'        ; 10/05/2015
  1990                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  1991                              <1> ; Last Modification: 26/02/2022
  1992                              <1> ; ----------------------------------------------------------------------------
  1993                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1994                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1995                              <1> ;
  1996                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  1997                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  1998                              <1> ; <Bell Laboratories (17/3/1972)>
  1999                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2000                              <1> ;
  2001                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2002                              <1> ;
  2003                              <1> ; ****************************************************************************
  2004                              <1> ; 23/11/2015
  2005                              <1> 
  2006                              <1> unkni: ; / used for all system calls
  2007                              <1> sysent: ; < enter to system call >
  2008                              <1> 	; 01/02/2022
  2009                              <1> 	; 19/10/2015
  2010                              <1> 	; 21/09/2015
  2011                              <1> 	; 01/07/2015
  2012                              <1> 	; 19/05/2015
  2013                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2014                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2015                              <1> 	;
  2016                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2017                              <1> 	; The trap type is determined and an indirect jump is made to 
  2018                              <1> 	; the appropriate system call handler. If there is a trap inside
  2019                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2020                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2021                              <1> 	; instructor is decoded to get the the system code part (see
  2022                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2023                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2024                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2025                              <1> 	; is called. If the call is legitimate control passes to the
  2026                              <1> 	; appropriate system routine.
  2027                              <1> 	;
  2028                              <1> 	; Calling sequence:
  2029                              <1> 	;	Through a trap caused by any sys call outside the system.
  2030                              <1> 	; Arguments:
  2031                              <1> 	;	Arguments of particular system call.	
  2032                              <1> 	; ...............................................................
  2033                              <1> 	;	
  2034                              <1> 	; Retro UNIX 8086 v1 modification: 
  2035                              <1> 	;       System call number is in EAX register.
  2036                              <1> 	;
  2037                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2038                              <1> 	;	registers depending of function details.
  2039                              <1>   	;
  2040                              <1> 	; 16/04/2015
  2041 00003A25 368925[F06E0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2042                              <1> 	; save user registers
  2043 00003A2C 1E                  <1> 	push	ds
  2044 00003A2D 06                  <1> 	push	es
  2045 00003A2E 0FA0                <1> 	push	fs
  2046 00003A30 0FA8                <1> 	push	gs
  2047 00003A32 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2048                              <1> 	;
  2049                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2050                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2051                              <1> 	;	for saving/restoring user registers.)
  2052                              <1> 	;
  2053 00003A33 50                  <1> 	push	eax ; 01/07/2015
  2054 00003A34 66B81000            <1> 	mov     ax, KDATA
  2055 00003A38 8ED8                <1>         mov     ds, ax
  2056 00003A3A 8EC0                <1>         mov     es, ax
  2057 00003A3C 8EE0                <1>         mov     fs, ax
  2058 00003A3E 8EE8                <1>         mov     gs, ax
  2059 00003A40 A1[486B0000]        <1> 	mov	eax, [k_page_dir]
  2060 00003A45 0F22D8              <1> 	mov	cr3, eax
  2061 00003A48 58                  <1> 	pop	eax ; 01/07/2015
  2062                              <1> 	; 19/10/2015
  2063 00003A49 FC                  <1> 	cld
  2064                              <1> 	;
  2065 00003A4A FE05[EF6E0000]      <1> 	inc	byte [sysflg]
  2066                              <1> 		; incb sysflg / indicate a system routine is in progress
  2067 00003A50 FB                  <1>         sti 	; 18/01/2014
  2068                              <1> 	;jnz	panic ; 24/05/2013
  2069                              <1> 		; beq 1f
  2070                              <1> 		; jmp panic ; / called if trap inside system
  2071                              <1> 	; 01/02/2022
  2072 00003A51 7405                <1> 	jz	short sysent_1
  2073 00003A53 E979F9FFFF          <1> 	jmp	panic
  2074                              <1> sysent_1:
  2075                              <1> ;1:	; 16/04/2015
  2076 00003A58 A3[F86E0000]        <1> 	mov	[u.r0], eax
  2077 00003A5D 8925[F46E0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2078                              <1> 	;
  2079                              <1> 		; mov $s.syst+2,clockp
  2080                              <1> 		; mov r0,-(sp) / save user registers 
  2081                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2082                              <1> 			   ; / in u.r0
  2083                              <1> 		; mov r1,-(sp)
  2084                              <1> 		; mov r2,-(sp)
  2085                              <1> 		; mov r3,-(sp)
  2086                              <1> 		; mov r4,-(sp)
  2087                              <1> 		; mov r5,-(sp)
  2088                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2089                              <1> 		             ; / arithmetic unit
  2090                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2091                              <1> 		             ; / extended arithmetic unit
  2092                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2093                              <1> 		             ; / arithmetic unit
  2094                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2095                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2096                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2097                              <1> 		; sub $sys,r0 / get xxx code
  2098 00003A63 C1E002              <1> 	shl	eax, 2
  2099                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2100 00003A66 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2101                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2102                              <1> 	;jnb	short badsys
  2103                              <1> 		; bhis badsys / yes, bad system call
  2104 00003A6B F5                  <1> 	cmc
  2105 00003A6C 9C                  <1> 	pushf	
  2106 00003A6D 50                  <1> 	push	eax
  2107 00003A6E 8B2D[F06E0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2108 00003A74 B0FE                <1> 	mov	al, 0FEh ; 11111110b
  2109 00003A76 1400                <1> 	adc	al, 0 ; al = al + cf
  2110 00003A78 204508              <1> 	and	[ebp+8], al ; flags (reset carry flag)
  2111                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2112                              <1> 				 ; / and clear carry bit
  2113 00003A7B 5D                  <1> 	pop	ebp ; eax
  2114 00003A7C 9D                  <1> 	popf
  2115                              <1> 	;jc	badsys
  2116                              <1> 	; 01/02/2022
  2117 00003A7D 7305                <1> 	jnc	short sysent_2
  2118 00003A7F E948010000          <1> 	jmp	badsys
  2119                              <1> sysent_2:
  2120 00003A84 A1[F86E0000]        <1> 	mov	eax, [u.r0]
  2121                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2122 00003A89 FFA5[8F3A0000]      <1> 	jmp	dword [ebp+syscalls]
  2123                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2124                              <1> 		            ; / to proper system routine.
  2125                              <1> syscalls: ; 1:
  2126                              <1> 	; 21/09/2015
  2127                              <1> 	; 01/07/2015
  2128                              <1> 	; 16/04/2015 (32 bit address modification) 
  2129 00003A8F [963B0000]          <1> 	dd sysrele	; / 0
  2130 00003A93 [3C3C0000]          <1> 	dd sysexit 	; / 1
  2131 00003A97 [673D0000]          <1> 	dd sysfork 	; / 2
  2132 00003A9B [6D3E0000]          <1> 	dd sysread 	; / 3
  2133 00003A9F [843E0000]          <1> 	dd syswrite 	; / 4
  2134 00003AA3 [EF3E0000]          <1> 	dd sysopen 	; / 5
  2135 00003AA7 [1E400000]          <1> 	dd sysclose 	; / 6
  2136 00003AAB [E23C0000]          <1> 	dd syswait 	; / 7
  2137 00003AAF [9B3F0000]          <1> 	dd syscreat 	; / 8
  2138 00003AB3 [D0430000]          <1> 	dd syslink 	; / 9
  2139 00003AB7 [8C440000]          <1> 	dd sysunlink 	; / 10
  2140 00003ABB [53450000]          <1> 	dd sysexec 	; / 11
  2141 00003ABF [874B0000]          <1> 	dd syschdir 	; / 12
  2142 00003AC3 [694C0000]          <1> 	dd systime 	; / 13
  2143 00003AC7 [D73F0000]          <1> 	dd sysmkdir 	; / 14
  2144 00003ACB [D94B0000]          <1> 	dd syschmod 	; / 15
  2145 00003ACF [394C0000]          <1> 	dd syschown 	; / 16
  2146 00003AD3 [9C4C0000]          <1> 	dd sysbreak 	; / 17
  2147 00003AD7 [11490000]          <1> 	dd sysstat 	; / 18
  2148 00003ADB [6C4D0000]          <1> 	dd sysseek 	; / 19
  2149 00003ADF [7E4D0000]          <1> 	dd systell 	; / 20
  2150 00003AE3 [3B580000]          <1> 	dd sysmount 	; / 21
  2151 00003AE7 [1A590000]          <1> 	dd sysumount 	; / 22
  2152 00003AEB [FA4D0000]          <1> 	dd syssetuid 	; / 23
  2153 00003AEF [2B4E0000]          <1> 	dd sysgetuid 	; / 24
  2154 00003AF3 [784C0000]          <1> 	dd sysstime 	; / 25
  2155 00003AF7 [EE4D0000]          <1> 	dd sysquit 	; / 26
  2156 00003AFB [E24D0000]          <1> 	dd sysintr 	; / 27
  2157 00003AFF [EE480000]          <1> 	dd sysfstat 	; / 28
  2158 00003B03 [36400000]          <1> 	dd sysemt 	; / 29
  2159 00003B07 [7E400000]          <1> 	dd sysmdate 	; / 30
  2160 00003B0B [D8400000]          <1> 	dd sysstty 	; / 31
  2161 00003B0F [C3420000]          <1> 	dd sysgtty 	; / 32
  2162 00003B13 [79400000]          <1> 	dd sysilgins 	; / 33
  2163 00003B17 [55610000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2164                              <1> 			     ; 11/06/2014
  2165 00003B1B [82610000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2166                              <1> 			     ; 01/07/2015
  2167 00003B1F [5A620000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2168                              <1> 			     ; 21/09/2015 - get last error number
  2169                              <1> end_of_syscalls:
  2170                              <1> 
  2171                              <1> error:
  2172                              <1> 	; 17/09/2015
  2173                              <1> 	; 03/09/2015
  2174                              <1> 	; 01/09/2015
  2175                              <1> 	; 09/06/2015
  2176                              <1> 	; 13/05/2015
  2177                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2178                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2179                              <1> 	;
  2180                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2181                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2182                              <1> 	;
  2183                              <1> 	; INPUTS -> none
  2184                              <1> 	; OUTPUTS ->
  2185                              <1> 	;	processor status - carry (c) bit is set (means error)
  2186                              <1> 	;
  2187                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2188                              <1> 	; 	      Because, jumps to error procedure
  2189                              <1> 	;	      disrupts push-pop nesting balance)
  2190                              <1> 	;
  2191 00003B23 8B2D[F06E0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2192 00003B29 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2193                              <1> 				 ; (system call will return with cf = 1)
  2194                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2195                              <1> 		               ; / users stack
  2196                              <1> 	; 17/09/2015
  2197 00003B2D 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2198                              <1> 				 ; for saving/restoring user registers	
  2199                              <1> 	;cmp	ebp, [u.usp]
  2200                              <1> 	;je	short err0	
  2201 00003B30 892D[F46E0000]      <1> 	mov	[u.usp], ebp
  2202                              <1> ;err0:
  2203                              <1> 	; 01/09/2015
  2204 00003B36 8B25[F46E0000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2205                              <1> 				    ; 10/04/2013
  2206                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2207                              <1> 				    ; related procedures will jump to 'error'
  2208                              <1> 				    ; procedure directly without returning to 
  2209                              <1> 				    ; the caller procedure. So, stack pointer
  2210                              <1>                                     ; must be restored here.)
  2211                              <1> 	; 13/05/2015
  2212                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2213                              <1> 	;	'get last error' system call later. 	
  2214                              <1> 
  2215                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2216 00003B3C C605[596F0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2217                              <1> 
  2218                              <1> sysret: ; < return from system call>
  2219                              <1> 	; 01/02/2022
  2220                              <1> 	; 10/09/2015
  2221                              <1> 	; 29/07/2015
  2222                              <1> 	; 25/06/2015
  2223                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2224                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2225                              <1> 	;
  2226                              <1> 	; 'sysret' first checks to see if process is about to be 
  2227                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2228                              <1> 	; If not, following happens:	 
  2229                              <1> 	; 	1) The user's stack pointer is restored.
  2230                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2231                              <1> 	;	   i-node has been modified. If it has, it is written out
  2232                              <1> 	;	   via 'ppoke'.
  2233                              <1> 	;	3) If the super block has been modified, it is written out
  2234                              <1> 	;	   via 'ppoke'.				
  2235                              <1> 	;	4) If the dismountable file system's super block has been
  2236                              <1> 	;	   modified, it is written out to the specified device
  2237                              <1> 	;	   via 'ppoke'.
  2238                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2239                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2240                              <1> 	;	   another user a chance to run.
  2241                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2242                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2243                              <1> 	;
  2244                              <1> 	; Calling sequence:
  2245                              <1> 	;	jump table or 'br sysret'
  2246                              <1> 	; Arguments: 
  2247                              <1> 	;	-	
  2248                              <1> 	; ...............................................................
  2249                              <1> 	;	
  2250                              <1> 	; ((AX=r1 for 'iget' input))
  2251                              <1> 	;	
  2252                              <1> 	;xor	ax, ax ; 04/05/2013
  2253                              <1> 	; 01/02/2022
  2254 00003B43 31C0                <1> 	xor	eax, eax
  2255                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2256 00003B45 FEC0                <1> 	inc	al ; 04/05/2013
  2257 00003B47 3805[406F0000]      <1> 	cmp	[u.bsys], al ; 1
  2258                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2259                              <1>         ;jnb	sysexit ; 04/05/2013
  2260                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2261                              <1> 	; 01/02/2022
  2262 00003B4D 7205                <1> 	jb	short sysret_2
  2263 00003B4F E9E8000000          <1> 	jmp	sysexit
  2264                              <1> sysret_2:
  2265                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2266                              <1> 		; mov u.sp,sp / no point stack to users stack
  2267 00003B54 FEC8                <1> 	dec 	al ; mov ax, 0
  2268                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2269 00003B56 E888160000          <1> 	call	iget
  2270                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2271                              <1> 		            ; / it is written out
  2272 00003B5B 6631C0              <1> 	xor 	ax, ax ; 0
  2273 00003B5E 3805[ED6E0000]      <1> 	cmp	[smod], al ; 0
  2274                              <1> 		; tstb	smod / has the super block been modified
  2275 00003B64 7614                <1> 	jna	short sysret1
  2276                              <1> 		; beq	1f / no, 1f
  2277 00003B66 A2[ED6E0000]        <1> 	mov	[smod], al ; 0
  2278                              <1> 		; clrb smod / yes, clear smod
  2279 00003B6B BB[A87B0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2280 00003B70 66810B0002          <1>    	or	word [ebx], 200h ;;
  2281                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2282                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2283                              <1> 		      	      ; / output
  2284                              <1> 	; AX = 0
  2285 00003B75 E80A220000          <1> 	call 	poke ; 07/08/2013
  2286                              <1> 	;call	ppoke
  2287                              <1> 	; AX = 0
  2288                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2289                              <1> sysret1: ;1:
  2290 00003B7A 3805[EE6E0000]      <1> 	cmp	[mmod], al ; 0
  2291                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2292                              <1> 		           ; / system
  2293 00003B80 7614                <1> 	jna	short sysrel0
  2294                              <1> 		; beq 1f / been modified?  no, 1f
  2295 00003B82 A2[EE6E0000]        <1> 	mov	[mmod], al ; 0	
  2296                              <1> 		; clrb	mmod / yes, clear mmod
  2297                              <1>         ;mov    ax, [mntd]
  2298                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2299 00003B87 BB[B07D0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2300                              <1>         ;;mov	[ebx], al
  2301                              <1> 	;mov    [sb1], al
  2302                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2303 00003B8C 66810B0002          <1> 	or	word [ebx], 200h
  2304                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2305                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2306 00003B91 E8EE210000          <1> 	call	poke ; 07/08/2013
  2307                              <1> 	;call	ppoke 
  2308                              <1> 		; jsr r0,ppoke / write it out to its device
  2309                              <1>         ;xor    al, al ; 26/04/2013       
  2310                              <1> ;1:
  2311                              <1> 		; tstb uquant / is the time quantum 0?
  2312                              <1> 		; bne 1f / no, don't swap it out
  2313                              <1> 
  2314                              <1> sysrele: ; < release >
  2315                              <1> 	; 14/10/2015
  2316                              <1> 	; 01/09/2015
  2317                              <1> 	; 24/07/2015
  2318                              <1> 	; 14/05/2015
  2319                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2320                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2321                              <1> 	;
  2322                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2323                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2324                              <1> 	; turns off the system flag. It then checked to see if there is
  2325                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2326                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2327                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2328                              <1> 	; the user, a rti is made.
  2329                              <1> 	;
  2330                              <1> 	; Calling sequence:
  2331                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2332                              <1> 	; Arguments:
  2333                              <1> 	;	-	
  2334                              <1> 	; ...............................................................
  2335                              <1> 	;	
  2336                              <1> 	; 23/02/2014 (swapret)
  2337                              <1> 	; 22/09/2013
  2338                              <1> sysrel0: ;1:
  2339 00003B96 803D[346F0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2340                              <1> 		; tstb uquant / is the time quantum 0?
  2341 00003B9D 7705                <1>         ja      short swapret
  2342                              <1> 		; bne 1f / no, don't swap it out
  2343                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2344 00003B9F E8D7120000          <1> 	call	tswap
  2345                              <1> 		; jsr r0,tswap / yes, swap it out
  2346                              <1> ;
  2347                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2348                              <1> swapret: ;1:
  2349                              <1> 	; 10/09/2015
  2350                              <1> 	; 01/09/2015
  2351                              <1> 	; 14/05/2015
  2352                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2353                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2354                              <1> 	; cli
  2355                              <1> 	; 24/07/2015
  2356                              <1> 	;
  2357                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2358                              <1> 	;; mov	esp, [u.usp]
  2359                              <1> 
  2360                              <1> 	; 22/09/2013
  2361 00003BA4 E8A9140000          <1> 	call	isintr
  2362                              <1> 	; 20/10/2013
  2363 00003BA9 7405                <1> 	jz	short sysrel1
  2364 00003BAB E875000000          <1> 	call	intract
  2365                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2366                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2367                              <1> 		               ; / action
  2368                              <1> sysrel1:
  2369 00003BB0 FA                  <1> 	cli ; 14/10/2015
  2370 00003BB1 FE0D[EF6E0000]      <1> 	dec	byte [sysflg]
  2371                              <1> 		; decb sysflg / turn system flag off
  2372 00003BB7 A1[4B6F0000]        <1> 	mov     eax, [u.pgdir]
  2373 00003BBC 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2374                              <1> 			  ; (others are different than kernel page tables) 
  2375                              <1> 	; 10/09/2015
  2376 00003BBF 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2377                              <1> 		; mov (sp)+,sc / restore user registers
  2378                              <1> 		; mov (sp)+,mq
  2379                              <1> 		; mov (sp)+,ac
  2380                              <1> 		; mov (sp)+,r5
  2381                              <1> 		; mov (sp)+,r4
  2382                              <1> 		; mov (sp)+,r3
  2383                              <1> 		; mov (sp)+,r2
  2384                              <1> 	;
  2385 00003BC0 A1[F86E0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2386 00003BC5 0FA9                <1> 	pop	gs
  2387 00003BC7 0FA1                <1> 	pop	fs
  2388 00003BC9 07                  <1> 	pop	es
  2389 00003BCA 1F                  <1> 	pop	ds
  2390 00003BCB CF                  <1> 	iretd	
  2391                              <1> 		; rti / no, return from interrupt
  2392                              <1> 
  2393                              <1> badsys:
  2394                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2395                              <1> 	; (Major Modification: 'core' dumping procedure in
  2396                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2397                              <1> 	;	has been changed to print 'Invalid System Call !'
  2398                              <1> 	;	message on the user's console tty.)
  2399                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2400                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2401                              <1> 	; (EAX = Function number)  
  2402                              <1> 	;
  2403 00003BCC FE05[406F0000]      <1> 	inc	byte [u.bsys]
  2404                              <1> 	;
  2405 00003BD2 8B1D[F06E0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2406 00003BD8 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2407 00003BDA E846DBFFFF          <1> 	call	dwordtohex
  2408 00003BDF 8915[A2680000]      <1> 	mov	[bsys_msg_eip], edx
  2409 00003BE5 A3[A6680000]        <1> 	mov	[bsys_msg_eip+4], eax
  2410 00003BEA A1[F86E0000]        <1> 	mov	eax, [u.r0]
  2411 00003BEF E831DBFFFF          <1> 	call	dwordtohex
  2412 00003BF4 8915[92680000]      <1> 	mov	[bsys_msg_eax], edx
  2413 00003BFA A3[96680000]        <1> 	mov	[bsys_msg_eax+4], eax
  2414 00003BFF 31C0                <1> 	xor	eax, eax
  2415 00003C01 C705[186F0000]-     <1>         mov     dword [u.base], badsys_msg ; "Invalid System call !"
  2415 00003C07 [73680000]          <1>
  2416 00003C0B 8B1D[086F0000]      <1> 	mov	ebx, [u.fofp]
  2417 00003C11 8903                <1> 	mov	[ebx], eax
  2418                              <1> 	;mov	eax, 1 ; inode number of console tty (for user)	
  2419 00003C13 40                  <1> 	inc	eax
  2420 00003C14 C705[1C6F0000]3B00- <1> 	mov	dword [u.count], BSYS_M_SIZE
  2420 00003C1C 0000                <1>
  2421                              <1> 		; writei
  2422                              <1> 		; INPUTS ->
  2423                              <1> 		;    r1 - inode number
  2424                              <1> 		;    u.count - byte count to be written
  2425                              <1> 		;    u.base - points to user buffer
  2426                              <1> 		;    u.fofp - points to word with current file offset
  2427                              <1> 		; OUTPUTS ->
  2428                              <1> 		;    u.count - cleared
  2429                              <1> 		;    u.nread - accumulates total bytes passed back	
  2430                              <1> 		;
  2431                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2432 00003C1E E882190000          <1> 	call	writei
  2433                              <1> 	;mov	eax, 1
  2434 00003C23 EB17                <1> 	jmp	sysexit
  2435                              <1> 
  2436                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2437                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2438                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2439                              <1> 		; br 1f / error
  2440                              <1> 		; neg r1 / negate the i-number to open the core image file
  2441                              <1> 		       ; / for writing
  2442                              <1> 		; jsr r0,iopen / open the core image file
  2443                              <1> 		; jsr r0,itrunc / free all associated blocks
  2444                              <1> 		; br 2f
  2445                              <1> ;1:
  2446                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2447                              <1> 		; jsr r0,maknod / make an i-node
  2448                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2449                              <1> ;2:
  2450                              <1> 		; mov $core,u.base / move address core to u.base
  2451                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2452                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2453                              <1> 		; clr u.off / clear user offset
  2454                              <1> 		; jsr r0,writei / write out the core image to the user
  2455                              <1> 		; mov $user,u.base / pt. u.base to user
  2456                              <1> 		; mov $64.,u.count / u.count = 64
  2457                              <1> 		; jsr r0,writei / write out all the user parameters
  2458                              <1> 		; neg r1 / make i-number positive
  2459                              <1> 		; jsr r0,iclose / close the core image file
  2460                              <1> 		; br sysexit /
  2461                              <1> ;3:
  2462                              <1> 		; <core\0\0>
  2463                              <1> 
  2464                              <1> intract: ; / interrupt action
  2465                              <1> 	; 14/10/2015
  2466                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2467                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2468                              <1> 	;
  2469                              <1> 	; Retro UNIX 8086 v1 modification !
  2470                              <1> 	; (Process/task switching and quit routine by using
  2471                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2472                              <1> 	;
  2473                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2474                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2475                              <1> 	;		'intract' will jump to 'sysexit'.
  2476                              <1> 	;	    Intract will return to the caller 
  2477                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2478                              <1> 	; 14/10/2015
  2479 00003C25 FB                  <1> 	sti
  2480                              <1> 	; 07/12/2013	
  2481 00003C26 66FF05[386F0000]    <1> 	inc 	word [u.quit]
  2482 00003C2D 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2483 00003C2F 66FF0D[386F0000]    <1> 	dec	word [u.quit]
  2484                              <1> 	; 16/04/2015
  2485 00003C36 C3                  <1> 	retn
  2486                              <1> intrct0:	
  2487 00003C37 58                  <1> 	pop	eax ; call intract -> retn
  2488                              <1> 	;
  2489 00003C38 31C0                <1> 	xor 	eax, eax
  2490 00003C3A FEC0                <1> 	inc	al  ; mov ax, 1
  2491                              <1> ;;;
  2492                              <1> 	; UNIX v1 original 'intract' routine... 
  2493                              <1> 	; / interrupt action
  2494                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2495                              <1> 		; bne 1f / no, 1f
  2496                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2497                              <1> 	; 1: / now in user area
  2498                              <1> 		; mov r1,-(sp) / save r1
  2499                              <1> 		; mov u.ttyp,r1 
  2500                              <1> 			; / pointer to tty buffer in control-to r1
  2501                              <1> 		; cmpb 6(r1),$177
  2502                              <1> 			; / is the interrupt char equal to "del"
  2503                              <1> 		; beq 1f / yes, 1f
  2504                              <1> 		; clrb 6(r1) 
  2505                              <1> 		        ; / no, clear the byte 
  2506                              <1> 			; / (must be a quit character)
  2507                              <1> 		; mov (sp)+,r1 / restore r1
  2508                              <1> 		; clr u.quit / clear quit flag
  2509                              <1> 		; bis $20,2(sp) 
  2510                              <1> 		    	; / set trace for quit (sets t bit of 
  2511                              <1> 			; / ps-trace trap)
  2512                              <1> 		; rti   ;  / return from interrupt
  2513                              <1> 	; 1: / interrupt char = del
  2514                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2515                              <1> 			   ; / in the buffer
  2516                              <1> 		; mov (sp)+,r1 / restore r1
  2517                              <1> 		; cmp u.intr,$core / should control be 
  2518                              <1> 				; / transferred to loc core?
  2519                              <1> 		; blo 1f
  2520                              <1> 		; jmp *u.intr / user to do rti yes, 
  2521                              <1> 				; / transfer to loc core
  2522                              <1> 	; 1:
  2523                              <1> 		; sys 1 / exit
  2524                              <1> 
  2525                              <1> sysexit: ; <terminate process>
  2526                              <1> 	; 01/02/2022
  2527                              <1> 	; 01/09/2015
  2528                              <1> 	; 31/08/2015
  2529                              <1> 	; 14/05/2015
  2530                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2531                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2532                              <1> 	;
  2533                              <1> 	; 'sysexit' terminates a process. First each file that
  2534                              <1> 	; the process has opened is closed by 'flose'. The process
  2535                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2536                              <1> 	; searched to find children of the dying process. If any of
  2537                              <1> 	; children are zombies (died by not waited for), they are
  2538                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2539                              <1> 	; dying process's parent. When the parent is found, it is
  2540                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2541                              <1> 	; one of these, the dying process just dies. If it is waiting
  2542                              <1> 	; for a child process to die, it notified that it doesn't 
  2543                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2544                              <1> 	; (waiting to active). It is awakened and put on runq by
  2545                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2546                              <1> 	; it will never be run again but stays around until a 'wait'
  2547                              <1> 	; is completed by it's parent process. If the parent is not
  2548                              <1> 	; found, process just dies. This means 'swap' is called with
  2549                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2550                              <1> 	; to write out the process and 'rswap' reads the new process
  2551                              <1> 	; over the one that dies..i.e., the dying process is 
  2552                              <1> 	; overwritten and destroyed.	
  2553                              <1>  	;
  2554                              <1> 	; Calling sequence:
  2555                              <1> 	;	sysexit or conditional branch.
  2556                              <1> 	; Arguments:
  2557                              <1> 	;	-	
  2558                              <1> 	; ...............................................................
  2559                              <1> 	;	
  2560                              <1> 	; Retro UNIX 8086 v1 modification: 
  2561                              <1> 	;       System call number (=1) is in EAX register.
  2562                              <1> 	;
  2563                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2564                              <1> 	;       registers depending of function details.
  2565                              <1> 	;
  2566                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2567                              <1> 	;
  2568                              <1> ; / terminate process
  2569                              <1> 	; AX = 1
  2570                              <1> 	;dec 	ax ; 0
  2571                              <1> 	; 01/02/2022
  2572 00003C3C 48                  <1> 	dec	eax ; 0
  2573 00003C3D 66A3[366F0000]      <1> 	mov	[u.intr], ax ; 0
  2574                              <1> 		; clr u.intr / clear interrupt control word
  2575                              <1> 		; clr r1 / clear r1
  2576                              <1> 	; AX = 0
  2577                              <1> sysexit_1: ; 1:
  2578                              <1> 	; AX = File descriptor
  2579                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2580                              <1> 		; / Search the whole list
  2581 00003C43 E85B0D0000          <1> 	call	fclose
  2582                              <1> 		; jsr r0,fclose / close all files the process opened
  2583                              <1> 	;; ignore error return
  2584                              <1> 		; br .+2 / ignore error return
  2585                              <1> 	;inc	ax
  2586 00003C48 FEC0                <1> 	inc	al
  2587                              <1> 		; inc r1 / increment file descriptor
  2588                              <1> 	;cmp	ax, 10
  2589 00003C4A 3C0A                <1> 	cmp	al, 10
  2590                              <1> 		; cmp r1,$10. / end of u.fp list?
  2591 00003C4C 72F5                <1> 	jb	short sysexit_1
  2592                              <1> 		; blt 1b / no, go back
  2593 00003C4E 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2594                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2595 00003C55 88A3[756C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2596                              <1> 		; clrb p.stat-1(r1) / free the process
  2597                              <1> 	;shl	bx, 1
  2598 00003C5B D0E3                <1> 	shl	bl, 1
  2599                              <1> 		; asl r1 / use r1 for index into the below tables
  2600 00003C5D 668B8B[146C0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2601                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2602 00003C64 668B93[346C0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2603                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2604                              <1> 	; xor 	bx, bx ; 0
  2605 00003C6B 30DB                <1> 	xor	bl, bl ; 0
  2606                              <1> 		; clr r2
  2607 00003C6D 31F6                <1> 	xor	esi, esi ; 0
  2608                              <1> 		; clr r5 / initialize reg
  2609                              <1> sysexit_2: ; 1:
  2610                              <1> 	        ; / find children of this dying process, 
  2611                              <1> 		; / if they are zombies, free them
  2612                              <1> 	;add	bx, 2
  2613 00003C6F 80C302              <1> 	add	bl, 2
  2614                              <1> 		; add $2,r2 / search parent process table 
  2615                              <1> 		          ; / for dying process's name
  2616 00003C72 66398B[346C0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2617                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2618 00003C79 7513                <1> 	jne	short sysexit_4
  2619                              <1> 		; bne 3f / no
  2620                              <1> 	;shr	bx, 1
  2621 00003C7B D0EB                <1> 	shr	bl, 1
  2622                              <1> 		; asr r2 / yes, it is a parent
  2623 00003C7D 80BB[756C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2624                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2625                              <1> 				     ; / dying process a zombie
  2626 00003C84 7506                <1> 	jne	short sysexit_3 
  2627                              <1> 		; bne 2f / no
  2628 00003C86 88A3[756C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2629                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2630                              <1> sysexit_3: ; 2:
  2631                              <1> 	;shr	bx, 1
  2632 00003C8C D0E3                <1> 	shl	bl, 1
  2633                              <1> 		; asl r2
  2634                              <1> sysexit_4: ; 3:
  2635                              <1> 		; / search the process name table 
  2636                              <1> 		; / for the dying process's parent
  2637 00003C8E 663993[146C0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2638                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2639 00003C95 7502                <1> 	jne	short sysexit_5
  2640                              <1> 		; bne 3f / no
  2641 00003C97 89DE                <1> 	mov	esi, ebx
  2642                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2643                              <1> 		          ; / process # x2) in r5
  2644                              <1> sysexit_5: ; 3:
  2645                              <1> 	;cmp	bx, nproc + nproc
  2646 00003C99 80FB20              <1> 	cmp	bl, nproc + nproc
  2647                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2648 00003C9C 72D1                <1> 	jb	short sysexit_2
  2649                              <1> 		; blt 1b / no, go back
  2650                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2651 00003C9E 21F6                <1> 	and	esi, esi ; r5=r1
  2652 00003CA0 7431                <1> 	jz	short sysexit_6
  2653                              <1> 		; beq 2f / no parent has been found. 
  2654                              <1> 		       ; / The process just dies
  2655 00003CA2 66D1EE              <1> 	shr	si, 1
  2656                              <1> 		; asr r1 / set up index to p.stat
  2657 00003CA5 8A86[756C0000]      <1> 	mov	al, [esi+p.stat-1]
  2658                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2659 00003CAB 20C0                <1> 	and	al, al
  2660 00003CAD 7424                <1> 	jz	short sysexit_6
  2661                              <1> 		; beq 2f / if its been freed, 2f
  2662 00003CAF 3C03                <1> 	cmp	al, 3
  2663                              <1> 		; cmp r2,$3 / is parent a zombie?
  2664 00003CB1 7420                <1> 	je	short sysexit_6
  2665                              <1> 		; beq 2f / yes, 2f
  2666                              <1> 	; BH = 0
  2667 00003CB3 8A1D[416F0000]      <1> 	mov	bl, [u.uno]
  2668                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2669 00003CB9 C683[756C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2670                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2671                              <1> 	; 05/02/2014
  2672 00003CC0 3C01                <1> 	cmp	al, 1 ; SRUN
  2673 00003CC2 740F                <1> 	je	short sysexit_6
  2674                              <1> 	;cmp	al, 2
  2675                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2676                              <1> 			  ; / this child to die
  2677                              <1> 	;jne	short sysexit_6	
  2678                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2679                              <1> 	; 05/02/2014
  2680                              <1> 	; p.stat = 2 --> waiting
  2681                              <1> 	; p.stat = 4 --> sleeping
  2682 00003CC4 C686[756C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2683                              <1> 	;dec	byte [esi+p.stat-1]
  2684                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2685 00003CCB 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2686                              <1> 	; 
  2687                              <1> 	;mov	ebx, runq + 4
  2688                              <1> 		; mov $runq+4,r2 / on the runq
  2689 00003CCE E87F120000          <1> 	call	putlu
  2690                              <1> 		; jsr r0, putlu
  2691                              <1> sysexit_6: ; 2:
  2692                              <1> 	; 31/08/2015
  2693                              <1> 		; / the process dies
  2694 00003CD3 C605[416F0000]00    <1> 	mov	byte [u.uno], 0
  2695                              <1> 		; clrb u.uno / put zero as the process number, 
  2696                              <1> 	           ; / so "swap" will
  2697 00003CDA E8A6110000          <1> 	call	swap
  2698                              <1> 		; jsr r0,swap / overwrite process with another process
  2699                              <1> hlt_sys:
  2700                              <1> 	;sti ; 18/01/2014
  2701                              <1> hlts0:
  2702 00003CDF F4                  <1> 	hlt
  2703 00003CE0 EBFD                <1> 	jmp	short hlts0
  2704                              <1> 		; 0 / and thereby kill it; halt?
  2705                              <1> 
  2706                              <1> 
  2707                              <1> syswait: ; < wait for a processs to die >
  2708                              <1> 	; 12/02/2022
  2709                              <1> 	; 01/02/2022
  2710                              <1> 	; 17/09/2015
  2711                              <1> 	; 02/09/2015
  2712                              <1> 	; 01/09/2015
  2713                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2714                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2715                              <1> 	;
  2716                              <1> 	; 'syswait' waits for a process die. 
  2717                              <1> 	; It works in following way:
  2718                              <1> 	;    1) From the parent process number, the parent's 
  2719                              <1> 	; 	process name is found. The p.ppid table of parent
  2720                              <1> 	;	names is then searched for this process name.
  2721                              <1> 	;	If a match occurs, r2 contains child's process
  2722                              <1> 	;	number. The child status is checked to see if it is
  2723                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2724                              <1> 	;	If it is, the child process is freed and it's name
  2725                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2726                              <1> 	;	If the child is not a zombie, nothing happens and
  2727                              <1> 	;	the search goes on through the p.ppid table until
  2728                              <1> 	;	all processes are checked or a zombie is found.
  2729                              <1> 	;    2) If no zombies are found, a check is made to see if
  2730                              <1> 	;	there are any children at all. If there are none,
  2731                              <1> 	;	an error return is made. If there are, the parent's
  2732                              <1> 	;	status is set to 2 (waiting for child to die),
  2733                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2734                              <1> 	;	is made to wait on the next process.
  2735                              <1> 	;
  2736                              <1> 	; Calling sequence:
  2737                              <1> 	;	?
  2738                              <1> 	; Arguments:
  2739                              <1> 	;	-
  2740                              <1> 	; Inputs: - 
  2741                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2742                              <1> 	; ...............................................................
  2743                              <1> 	;				
  2744                              <1> 	
  2745                              <1> ; / wait for a process to die
  2746                              <1> 
  2747                              <1> syswait_0:
  2748 00003CE2 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2749                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2750 00003CE9 D0E3                <1> 	shl	bl, 1
  2751                              <1> 	;shl	bx, 1
  2752                              <1> 		; asl r1 / x2 to get index into p.pid table
  2753 00003CEB 668B83[146C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2754                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2755 00003CF2 31F6                <1> 	xor	esi, esi
  2756                              <1> 		; clr r2
  2757 00003CF4 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2758                              <1> 	;xor 	cl, cl
  2759                              <1> 		; clr r3 / initialize reg 3
  2760                              <1> syswait_1: ; 1:
  2761                              <1> 	; 12/02/2022
  2762 00003CF6 46                  <1> 	inc	esi
  2763 00003CF7 46                  <1> 	inc	esi
  2764                              <1> 	;add	si, 2
  2765                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2766                              <1> 			  ; / search table of parent processes 
  2767                              <1> 			  ; / for this process name
  2768 00003CF8 663B86[346C0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2769                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2770                              <1> 			            ; / process number
  2771 00003CFF 7531                <1> 	jne	short syswait_3
  2772                              <1> 		; bne 3f / branch if no match of parent process name
  2773                              <1> 	;inc	cx
  2774 00003D01 FEC1                <1> 	inc	cl
  2775                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2776                              <1> 	; 12/02/2022
  2777 00003D03 D1EE                <1> 	shr	esi, 1
  2778                              <1> 	;shr	si, 1
  2779                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2780                              <1> 	; The possible states ('p.stat' values) of a process are:
  2781                              <1> 	;	0 = free or unused
  2782                              <1> 	;	1 = active
  2783                              <1> 	;	2 = waiting for a child process to die
  2784                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2785 00003D05 80BE[756C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2786                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2787 00003D0C 7522                <1> 	jne	short syswait_2
  2788                              <1> 		; bne 2f / no, skip it
  2789 00003D0E 88BE[756C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2790                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2791                              <1> 	; 12/02/2022
  2792 00003D14 D1E6                <1> 	shl	esi, 1
  2793                              <1> 	;shl	si, 1
  2794                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2795 00003D16 0FB786[146C0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2796 00003D1D A3[F86E0000]        <1> 	mov	[u.r0], eax
  2797                              <1> 		; mov p.pid-2(r2),*u.r0 
  2798                              <1> 			      ; / put childs process name in (u.r0)
  2799                              <1> 	;
  2800                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2801                              <1> 	;
  2802                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2803                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2804                              <1> 	; system call loop from the application/program if it calls
  2805                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2806                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2807                              <1> 	;
  2808                              <1> 	; Note: syswait will return with error if there is not a
  2809                              <1> 	;       zombie or running process to wait.	
  2810                              <1> 	;
  2811                              <1> 	;sub	ax, ax
  2812                              <1> 	; 01/02/2022
  2813 00003D22 29C0                <1> 	sub	eax, eax
  2814 00003D24 668986[346C0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2815 00003D2B E915FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2816                              <1> 	;
  2817                              <1> 	;jmp	sysret
  2818                              <1> 		; br sysret1 / return cause child is dead
  2819                              <1> syswait_2: ; 2:
  2820                              <1> 	; 12/02/2022
  2821 00003D30 D1E6                <1> 	shl	esi, 1
  2822                              <1> 	;shl	si, 1
  2823                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2824                              <1> syswait_3: ; 3:
  2825 00003D32 6683FE20            <1> 	cmp	si, nproc+nproc
  2826                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2827 00003D36 72BE                <1> 	jb	short syswait_1
  2828                              <1> 		; blt 1b / no, continue search
  2829                              <1> 	;and	cx, cx
  2830 00003D38 20C9                <1> 	and	cl, cl
  2831                              <1> 		; tst r3 / one gets here if there are no children 
  2832                              <1> 		       ; / or children that are still active
  2833                              <1> 	; 30/10/2013
  2834 00003D3A 7515                <1> 	jnz	short syswait_4
  2835                              <1> 	;jz	error
  2836                              <1> 		; beq error1 / there are no children, error
  2837 00003D3C 890D[F86E0000]      <1> 	mov	[u.r0], ecx ; 0
  2838                              <1> 	; 12/02/2022
  2839 00003D42 C705[476F0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2839 00003D4A 0000                <1>
  2840                              <1> 			; miscellaneous/other errors
  2841 00003D4C E9D2FDFFFF          <1> 	jmp	error
  2842                              <1> syswait_4:
  2843 00003D51 8A1D[416F0000]      <1> 	mov	bl, [u.uno]
  2844                              <1> 		; movb u.uno,r1 / there are children so put 
  2845                              <1> 			      ; / parent process number in r1
  2846 00003D57 FE83[756C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2847                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2848                              <1> 				  ; / other children to die
  2849                              <1> 	; 04/11/2013
  2850 00003D5D E823110000          <1> 	call	swap
  2851                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2852 00003D62 E97BFFFFFF          <1> 	jmp	syswait_0
  2853                              <1> 		; br syswait / wait on next process
  2854                              <1> 
  2855                              <1> sysfork: ; < create a new process >
  2856                              <1> 	; 26/02/2022
  2857                              <1> 	; 25/02/2022
  2858                              <1> 	; 01/02/2022
  2859                              <1> 	; 18/09/2015
  2860                              <1> 	; 04/09/2015
  2861                              <1> 	; 02/09/2015
  2862                              <1> 	; 01/09/2015
  2863                              <1> 	; 28/08/2015
  2864                              <1> 	; 14/05/2015
  2865                              <1> 	; 10/05/2015
  2866                              <1> 	; 09/05/2015
  2867                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2868                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2869                              <1> 	;
  2870                              <1> 	; 'sysfork' creates a new process. This process is referred
  2871                              <1> 	; to as the child process. This new process core image is
  2872                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2873                              <1> 	; distinction is the return location and the fact that (u.r0)
  2874                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2875                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2876                              <1> 	; 'sysfork' works in the following manner: 	
  2877                              <1> 	;    1) The process status table (p.stat) is searched to find
  2878                              <1> 	;	a process number that is unused. If none are found
  2879                              <1> 	;	an error occurs.
  2880                              <1> 	;    2) when one is found, it becomes the child process number
  2881                              <1> 	;	and it's status (p.stat) is set to active.
  2882                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2883                              <1> 	;	character in that tty buffer is cleared.
  2884                              <1> 	;    4) The child process is put on the lowest priority run 
  2885                              <1> 	;	queue via 'putlu'.
  2886                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2887                              <1> 	;	it is a unique number) and is put in the child's unique
  2888                              <1> 	;	identifier; process id (p.pid).
  2889                              <1> 	;    6) The process name of the parent is then obtained and
  2890                              <1> 	;	placed in the unique identifier of the parent process
  2891                              <1> 	;	name is then put in 'u.r0'.	
  2892                              <1> 	;    7) The child process is then written out on disk by
  2893                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2894                              <1> 	;	and the child is born. (The child process is written 
  2895                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2896                              <1> 	;	number.)
  2897                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2898                              <1> 	;    9) The child process name is put in 'u.r0'.
  2899                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2900                              <1> 	;	create the return address for the parent process.
  2901                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2902                              <1> 	;	the parent has opened. For each file the parent has
  2903                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2904                              <1> 	;	to indicate that the child process also has opened
  2905                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2906                              <1> 	;
  2907                              <1> 	; Calling sequence:
  2908                              <1> 	;	from shell ?
  2909                              <1> 	; Arguments:
  2910                              <1> 	;	-
  2911                              <1> 	; Inputs: -
  2912                              <1> 	; Outputs: *u.r0 - child process name
  2913                              <1> 	; ...............................................................
  2914                              <1> 	;	
  2915                              <1> 	; Retro UNIX 8086 v1 modification: 
  2916                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2917                              <1> 	;	= process id of child a parent process returns
  2918                              <1> 	;	= process id of parent when a child process returns
  2919                              <1> 	;
  2920                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  2921                              <1> 	;	in following manner: (with an example: c library, fork)
  2922                              <1> 	;	
  2923                              <1> 	;	1:
  2924                              <1> 	;		sys	fork
  2925                              <1> 	;			br 1f  / child process returns here
  2926                              <1> 	;		bes	2f     / parent process returns here
  2927                              <1> 	;		/ pid of new process in r0
  2928                              <1> 	;		rts	pc
  2929                              <1> 	;	2: / parent process condionally branches here
  2930                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  2931                              <1> 	;		rts	pc
  2932                              <1> 	;
  2933                              <1> 	;	1: / child process brances here
  2934                              <1> 	;		clr	r0   / pid = 0 in child process
  2935                              <1> 	;		rts	pc
  2936                              <1> 	;
  2937                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  2938                              <1> 	;		// pid = fork();
  2939                              <1> 	;		//
  2940                              <1> 	;		// pid == 0 in child process; 
  2941                              <1> 	;		// pid == -1 means error return
  2942                              <1> 	;		// in child, 
  2943                              <1> 	;		//	parents id is in par_uid if needed
  2944                              <1> 	;		
  2945                              <1> 	;		_fork:
  2946                              <1> 	;			mov	$.fork,eax
  2947                              <1> 	;			int	$0x30
  2948                              <1> 	;			jmp	1f
  2949                              <1> 	;			jnc	2f
  2950                              <1> 	;			jmp	cerror
  2951                              <1> 	;		1:
  2952                              <1> 	;			mov	eax,_par_uid
  2953                              <1> 	;			xor	eax,eax
  2954                              <1> 	;		2:
  2955                              <1> 	;			ret
  2956                              <1> 	;
  2957                              <1> 	;	In Retro UNIX 8086 v1,
  2958                              <1> 	;	'sysfork' returns in following manner:
  2959                              <1> 	;	
  2960                              <1> 	;		mov	ax, sys_fork
  2961                              <1> 	;		mov	bx, offset @f ; routine for child
  2962                              <1> 	;		int	20h
  2963                              <1> 	;		jc	error
  2964                              <1> 	;		
  2965                              <1> 	;	; Routine for parent process here (just after 'jc')
  2966                              <1> 	;		mov	word ptr [pid_of_child], ax
  2967                              <1> 	;		jmp	next_routine_for_parent	
  2968                              <1> 	;
  2969                              <1> 	;	@@: ; routine for child process here				
  2970                              <1> 	;		....	
  2971                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  2972                              <1> 	;	       for child process by using BX input.
  2973                              <1> 	;	      (at first, parent process will return then 
  2974                              <1> 	;	      child process will return -after swapped in-
  2975                              <1> 	;	      'syswait' is needed in parent process
  2976                              <1> 	;	      if return from child process will be waited for.)
  2977                              <1> 	;	  				
  2978                              <1> 	
  2979                              <1> ; / create a new process
  2980                              <1> 	; EBX = return address for child process 
  2981                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  2982 00003D67 31F6                <1> 	xor 	esi, esi
  2983                              <1> 		; clr r1
  2984                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  2985 00003D69 46                  <1> 	inc	esi
  2986                              <1> 		; inc r1
  2987 00003D6A 80BE[756C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  2988                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  2989 00003D71 760B                <1> 	jna	short sysfork_2	
  2990                              <1> 		; beq 1f / it's unused so branch
  2991 00003D73 6683FE10            <1> 	cmp	si, nproc
  2992                              <1> 		; cmp r1,$nproc / all processes checked
  2993 00003D77 72F0                <1> 	jb	short sysfork_1
  2994                              <1> 		; blt 1b / no, branch back
  2995                              <1> 	;
  2996                              <1> 	; Retro UNIX 8086 v1. modification:
  2997                              <1> 	;	Parent process returns from 'sysfork' to address 
  2998                              <1> 	;	which is just after 'sysfork' system call in parent
  2999                              <1> 	;	process. Child process returns to address which is put
  3000                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3001                              <1> 	;
  3002                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3003                              <1> 		               ; / to old process return
  3004                              <1> 		; br error1 / no room for a new process
  3005                              <1> sysfork_err:
  3006 00003D79 E9A5FDFFFF          <1> 	jmp	error
  3007                              <1> sysfork_2: ; 1:
  3008 00003D7E E865F0FFFF          <1> 	call	allocate_page
  3009                              <1> 	;jc	error
  3010                              <1> 	; 01/02/2022
  3011 00003D83 72F4                <1> 	jc	short sysfork_err
  3012 00003D85 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3013                              <1> 	; Retro UNIX 386 v1 modification!
  3014 00003D86 E856F2FFFF          <1> 	call	duplicate_page_dir
  3015                              <1> 		; EAX = New page directory 
  3016 00003D8B 7308                <1> 	jnc	short sysfork_3
  3017 00003D8D 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3018 00003D8E E81DF2FFFF          <1> 	call 	deallocate_page
  3019                              <1> 	;jmp	error
  3020                              <1> 	; 01/02/2022
  3021 00003D93 EBE4                <1> 	jmp	short sysfork_err
  3022                              <1> sysfork_3:
  3023                              <1> 	; Retro UNIX 386 v1 modification !
  3024 00003D95 56                  <1> 	push	esi
  3025 00003D96 E861110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3026                              <1> 		      ; and interrupt return components (for IRET)
  3027 00003D9B 8705[4B6F0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3028 00003DA1 A3[4F6F0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3029 00003DA6 5E                  <1> 	pop	esi
  3030 00003DA7 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3031                              <1> 		; [u.usp] = esp
  3032 00003DA8 89F7                <1> 	mov	edi, esi
  3033                              <1> 	;shl	di, 2
  3034                              <1> 	; 12/02/2022
  3035 00003DAA C1E702              <1> 	shl	edi, 2
  3036 00003DAD 8987[826C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3037 00003DB3 A3[426F0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3038                              <1> 	; 28/08/2015
  3039 00003DB8 0FB605[416F0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3040                              <1> 		; movb u.uno,-(sp) / save parent process number
  3041 00003DBF 89C7                <1> 	mov	edi, eax
  3042 00003DC1 50                  <1>         push	eax ; ** 
  3043 00003DC2 8A87[556C0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3044                              <1> 	; 18/09/2015
  3045 00003DC8 8886[556C0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3046                              <1> 	; 26/02/2022 (p.waitc is not used)
  3047                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3048                              <1> 	; 25/02/2022 (BugFix)
  3049                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3050                              <1> 	;			   ; ah - reset child's wait channel	
  3051 00003DCE 89F0                <1> 	mov	eax, esi
  3052 00003DD0 A2[416F0000]        <1> 	mov	[u.uno], al ; child process number
  3053                              <1> 		;movb r1,u.uno / set child process number to r1
  3054 00003DD5 FE86[756C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3055                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3056                              <1> 				  ; / process to active status
  3057                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3058                              <1> 			      ; / control tty buffer in r2
  3059                              <1>                 ; beq 2f / branch, if no such tty assigned
  3060                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3061                              <1> 	; 2:
  3062 00003DDB 53                  <1> 	push	ebx  ; * return address for the child process
  3063                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3064                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3065                              <1> 		; mov $runq+4,r2
  3066 00003DDC E871110000          <1> 	call	putlu 
  3067                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3068                              <1> 			   ; / run queue
  3069                              <1> 	; 12/02/2022
  3070 00003DE1 D1E6                <1> 	shl	esi, 1
  3071                              <1> 	;shl	si, 1
  3072                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3073                              <1> 		       ; / into p.pid table
  3074 00003DE3 66FF05[E66E0000]    <1> 	inc	word [mpid]
  3075                              <1> 		; inc mpid / increment m.pid; get a new process name
  3076 00003DEA 66A1[E66E0000]      <1> 	mov	ax, [mpid]
  3077 00003DF0 668986[146C0000]    <1> 	mov	[esi+p.pid-2], ax
  3078                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3079                              <1> 				    ; / in child process' name slot
  3080 00003DF7 5A                  <1> 	pop	edx  ; * return address for the child process
  3081                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3082 00003DF8 5B                  <1>   	pop	ebx  ; **
  3083                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3084                              <1> 		; movb (sp),r2 / put parent process number in r2
  3085                              <1> 	; 01/02/2022
  3086 00003DF9 D0E3                <1> 	shl	bl, 1
  3087                              <1> 	;shl 	bx, 1
  3088                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3089                              <1> 	; ebx <= 32
  3090                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3091 00003DFB 668B83[146C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3092                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3093                              <1> 				   ; / process
  3094 00003E02 668986[346C0000]    <1> 	mov	[esi+p.ppid-2], ax
  3095                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3096                              <1> 			  ; / in parent process slot for child
  3097 00003E09 A3[F86E0000]        <1> 	mov	[u.r0], eax	
  3098                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3099                              <1> 			     ; / at location where r0 was saved
  3100 00003E0E 8B2D[F06E0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3101 00003E14 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3102                              <1> 			   ; * return address for the child process
  3103                              <1> 		; mov $sysret1,-(sp) /
  3104                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3105                              <1> 			      ; / user is swapped out
  3106                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3107                              <1> 	; 04/09/2015 - 01/09/2015
  3108                              <1> 	; [u.usp] = esp
  3109 00003E17 68[433B0000]        <1> 	push	sysret ; ***
  3110 00003E1C 8925[F46E0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3111                              <1> 			     ; (for child process)	
  3112 00003E22 31C0                <1> 	xor 	eax, eax
  3113 00003E24 66A3[286F0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3114                              <1> 	;
  3115 00003E2A E8CD100000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3116                              <1> 		;jsr r0,wswap / put child process out on drum
  3117                              <1> 		;jsr r0,unpack / unpack user stack
  3118                              <1> 		;mov u.usp,sp / restore user stack pointer
  3119                              <1> 		; tst (sp)+ / bump stack pointer
  3120                              <1> 	; Retro UNIX 386 v1 modification !
  3121 00003E2F 58                  <1> 	pop	eax ; ***
  3122                              <1> 	;shl	bx, 1
  3123                              <1> 	; 01/02/2022
  3124 00003E30 D0E3                <1> 	shl	bl, 1 
  3125                              <1> 		; ebx <= 64
  3126 00003E32 8B83[826C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3127 00003E38 E8E8100000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3128                              <1> 		      ; registers and return address (for IRET)
  3129                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3130 00003E3D 0FB705[E66E0000]    <1>         movzx   eax, word [mpid]
  3131 00003E44 A3[F86E0000]        <1> 	mov	[u.r0], eax
  3132                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3133                              <1> 			       ; / where r0 was saved
  3134                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3135                              <1> 			       ; / process return
  3136                              <1> 	;xor	ebx, ebx
  3137 00003E49 31F6                <1> 	xor     esi, esi
  3138                              <1> 		;clr r1
  3139                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3140                              <1> 	      ; / opened by the parent process
  3141                              <1> 	; 01/09/2015
  3142                              <1> 	;xor	bh, bh
  3143                              <1> 	;mov 	bl, [esi+u.fp]
  3144 00003E4B 8A86[FE6E0000]      <1> 	mov 	al, [esi+u.fp]
  3145                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3146                              <1>         ;or	bl, bl
  3147 00003E51 08C0                <1> 	or	al, al
  3148 00003E53 740C                <1> 	jz	short sysfork_5	
  3149                              <1> 		; beq 2f / file has not been opened by parent, 
  3150                              <1> 		       ; / so branch
  3151 00003E55 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3152 00003E57 F6E4                <1> 	mul	ah
  3153                              <1> 	;;movzx	ebx, ax
  3154                              <1> 	;mov	bx, ax
  3155 00003E59 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3156                              <1> 	;shl	bx, 3
  3157                              <1> 		; asl r2 / multiply by 8
  3158                              <1>        		; asl r2 / to get index into fsp table
  3159                              <1>        		; asl r2
  3160 00003E5B FE83[C46C0000]      <1>   	inc     byte [ebx+fsp-2]
  3161                              <1> 		; incb fsp-2(r2) / increment number of processes
  3162                              <1> 			     ; / using file, because child will now be
  3163                              <1> 			     ; / using this file
  3164                              <1> sysfork_5: ; 2:
  3165 00003E61 46                  <1>         inc     esi
  3166                              <1> 		; inc r1 / get next open file
  3167 00003E62 6683FE0A            <1>         cmp     si, 10
  3168                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3169                              <1> 			    ; / can be opened
  3170 00003E66 72E3                <1> 	jb	short sysfork_4	
  3171                              <1> 		; blt 1b / check next entry
  3172 00003E68 E9D6FCFFFF          <1> 	jmp	sysret
  3173                              <1> 		; br sysret1
  3174                              <1> 
  3175                              <1> sysread: ; < read from file >
  3176                              <1> 	; 01/02/2022
  3177                              <1> 	; 13/05/2015
  3178                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3179                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3180                              <1> 	;
  3181                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3182                              <1> 	; characters to be read. If finds the file from the file
  3183                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3184                              <1> 	; is returned from a successful open call (sysopen).
  3185                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3186                              <1> 	; is read into core via 'readi'.
  3187                              <1> 	;
  3188                              <1> 	; Calling sequence:
  3189                              <1> 	;	sysread; buffer; nchars
  3190                              <1> 	; Arguments:
  3191                              <1> 	;	buffer - location of contiguous bytes where 
  3192                              <1> 	;		 input will be placed.
  3193                              <1> 	;	nchars - number of bytes or characters to be read.
  3194                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3195                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3196                              <1> 	; ...............................................................
  3197                              <1> 	;				
  3198                              <1> 	; Retro UNIX 8086 v1 modification: 
  3199                              <1> 	;       'sysread' system call has three arguments; so,
  3200                              <1> 	;	* 1st argument, file descriptor is in BX register
  3201                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3202                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3203                              <1> 	;
  3204                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3205                              <1> 	;	to the user with number of bytes read. 
  3206                              <1> 	;
  3207 00003E6D E83A000000          <1> 	call	rw1
  3208 00003E72 0F82ABFCFFFF        <1> 	jc	error ; 13/05/2015, ax < 1
  3209                              <1> 		; jsr r0,rw1 / get i-number of file to be read into r1
  3210 00003E78 F6C480              <1> 	test	ah, 80h
  3211                              <1> 		; tst r1 / negative i-number?
  3212                              <1> 	;jnz	error
  3213                              <1> 		; ble error1 / yes, error 1 to read
  3214                              <1> 			   ; / it should be positive
  3215                              <1> 	; 01/02/2022
  3216 00003E7B 750E                <1> 	jnz	short rw_error
  3217 00003E7D E835150000          <1> 	call	readi
  3218                              <1> 		; jsr r0,readi / read data into core
  3219 00003E82 EB19                <1> 	jmp	short rw0
  3220                              <1> 		; br 1f
  3221                              <1> syswrite: ; < write to file >
  3222                              <1> 	; 01/02/2022
  3223                              <1> 	; 13/05/2015
  3224                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3225                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3226                              <1> 	;
  3227                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3228                              <1> 	; and the number of characters to write. If finds the file
  3229                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3230                              <1> 	; descriptor is returned from a successful open or create call
  3231                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3232                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3233                              <1> 	;
  3234                              <1> 	; Calling sequence:
  3235                              <1> 	;	syswrite; buffer; nchars
  3236                              <1> 	; Arguments:
  3237                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3238                              <1> 	;	nchars - number of characters to be written.
  3239                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3240                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3241                              <1> 	; ...............................................................
  3242                              <1> 	;				
  3243                              <1> 	; Retro UNIX 8086 v1 modification: 
  3244                              <1> 	;       'syswrite' system call has three arguments; so,
  3245                              <1> 	;	* 1st argument, file descriptor is in BX register
  3246                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3247                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3248                              <1> 	;
  3249                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3250                              <1> 	;	to the user with number of bytes written. 
  3251                              <1> 	;
  3252 00003E84 E823000000          <1> 	call	rw1
  3253                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3254                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3255                              <1> 	; 01/02/2022
  3256 00003E89 7305                <1> 	jnc	short syswrite_1
  3257                              <1> rw_error:
  3258 00003E8B E993FCFFFF          <1> 	jmp	error
  3259                              <1> syswrite_1:
  3260 00003E90 F6C480              <1>         test	ah, 80h
  3261                              <1> 		; tst r1 / positive i-number ?
  3262 00003E93 744E                <1>         jz	short rw3 ; 13/05/2015
  3263                              <1> 	;jz	error
  3264                              <1> 		; bge error1 / yes, error 1 
  3265                              <1> 			   ; / negative i-number means write
  3266 00003E95 66F7D8              <1> 	neg	ax
  3267                              <1> 		; neg r1 / make it positive
  3268 00003E98 E808170000          <1> 	call	writei
  3269                              <1>         	; jsr r0,writei / write data
  3270                              <1> rw0: ; 1:
  3271 00003E9D A1[206F0000]        <1>         mov	eax, [u.nread]
  3272 00003EA2 A3[F86E0000]        <1> 	mov	[u.r0], eax
  3273                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3274                              <1> 				  ; / into (u.r0)
  3275 00003EA7 E997FCFFFF          <1> 	jmp	sysret
  3276                              <1>         	; br sysret1
  3277                              <1> rw1:	
  3278                              <1> 	; 14/05/2015
  3279                              <1> 	; 13/05/2015
  3280                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3281                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3282                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3283                              <1> 	;
  3284                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3285                              <1> 				;(in the user's virtual memory space)
  3286                              <1> 	;mov	[u.count], edx 
  3287                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3288                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3289                              <1> 	;;mov	eax, ebx ; file descriptor
  3290                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3291                              <1> 		             ; / (index to u.fp table) in r1
  3292                              <1> 	; 13/05/2015
  3293 00003EAC C705[F86E0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3293 00003EB4 0000                <1>
  3294                              <1> 	;
  3295                              <1> 	;; call	getf
  3296                              <1>         ; eBX = File descriptor
  3297 00003EB6 E82B0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3298                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3299                              <1> 	; AX = I-number of the file ; negative i-number means write
  3300                              <1> 	; 13/05/2015
  3301 00003EBB 6683F801            <1> 	cmp 	ax, 1
  3302 00003EBF 7217                <1> 	jb	short rw2
  3303                              <1> 	;
  3304 00003EC1 890D[186F0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3305                              <1> 				;(in the user's virtual memory space)
  3306 00003EC7 8915[1C6F0000]      <1> 	mov	[u.count], edx 
  3307                              <1> 	; 14/05/2015
  3308 00003ECD C705[476F0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3308 00003ED5 0000                <1>
  3309 00003ED7 C3                  <1> 	retn
  3310                              <1>         	; rts r0
  3311                              <1> rw2:
  3312                              <1> 	; 13/05/2015
  3313 00003ED8 C705[476F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3313 00003EE0 0000                <1>
  3314 00003EE2 C3                  <1> 	retn
  3315                              <1> rw3: 
  3316                              <1> 	; 13/05/2015
  3317 00003EE3 C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3317 00003EEB 0000                <1>
  3318 00003EED F9                  <1> 	stc
  3319 00003EEE C3                  <1> 	retn
  3320                              <1> 
  3321                              <1> sysopen: ;<open file>
  3322                              <1> 	; 12/02/2022
  3323                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3324                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3325                              <1> 	;
  3326                              <1> 	; 'sysopen' opens a file in following manner:
  3327                              <1> 	;    1) The second argument in a sysopen says whether to
  3328                              <1> 	;	open the file ro read (0) or write (>0).
  3329                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3330                              <1> 	;    3) The file is opened by 'iopen'.
  3331                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3332                              <1> 	;	and the user's open file list - u.fp.
  3333                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3334                              <1> 	;	b) An entry for the file is created in the fsp table.
  3335                              <1> 	;	c) The number of this entry is put on u.fp list.
  3336                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3337                              <1> 	;	   to by u.r0.
  3338                              <1> 	;
  3339                              <1> 	; Calling sequence:
  3340                              <1> 	;	sysopen; name; mode
  3341                              <1> 	; Arguments:
  3342                              <1> 	;	name - file name or path name
  3343                              <1> 	;	mode - 0 to open for reading
  3344                              <1> 	;	       1 to open for writing
  3345                              <1> 	; Inputs: (arguments)
  3346                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3347                              <1> 	;		  is put into r0's location on the stack.	
  3348                              <1> 	; ...............................................................
  3349                              <1> 	;				
  3350                              <1> 	; Retro UNIX 8086 v1 modification: 
  3351                              <1> 	;       'sysopen' system call has two arguments; so,
  3352                              <1> 	;	* 1st argument, name is pointed to by BX register
  3353                              <1> 	;	* 2nd argument, mode is in CX register
  3354                              <1> 	;
  3355                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3356                              <1> 	;	to the user with the file descriptor/number 
  3357                              <1> 	;	(index to u.fp list).
  3358                              <1> 	;
  3359                              <1> 	;call	arg2
  3360                              <1> 	; * name - 'u.namep' points to address of file/path name
  3361                              <1> 	;          in the user's program segment ('u.segmnt')
  3362                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3363                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3364                              <1> 	;          which is on top of stack.
  3365                              <1> 	;
  3366                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3367                              <1> 	;
  3368                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3369                              <1> 
  3370 00003EEF 891D[106F0000]      <1> 	mov	[u.namep], ebx
  3371                              <1> 	;push	cx
  3372 00003EF5 51                  <1> 	push	ecx ; 12/02/2022
  3373 00003EF6 E81E0B0000          <1> 	call	namei
  3374                              <1> 		; jsr r0,namei / i-number of file in r1
  3375                              <1>      	;and	ax, ax
  3376                              <1> 	;jz	error ; File not found
  3377 00003EFB 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3378                              <1> 	;jc	error ; 27/05/2013
  3379                              <1> 		; br  error2 / file not found
  3380                              <1>    	;pop	dx ; mode
  3381                              <1> 	;push	dx
  3382                              <1> 	; 12/02/2022
  3383                              <1> 	;pop	edx ; * ; mode
  3384                              <1> 	;push	edx ; *
  3385 00003EFD 8B1424              <1> 	mov	edx, [esp] ; *
  3386                              <1> 	; edx = open mode (0 or 1)
  3387                              <1> 	;or	dx, dx
  3388 00003F00 08D2                <1> 	or	dl, dl
  3389                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3390                              <1> 		         ; / 0 means, open for read)
  3391 00003F02 7403                <1> 	jz	short sysopen_0
  3392                              <1> 		; beq 1f / yes, leave i-number positive
  3393                              <1> syscreat_0: 
  3394                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3395 00003F04 66F7D8              <1> 	neg	ax
  3396                              <1>         	; neg r1 / open for writing so make i-number negative
  3397                              <1> sysopen_0: ;1:
  3398 00003F07 E85B1A0000          <1> 	call	iopen
  3399                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3400 00003F0C 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3401                              <1> 	;and	dx, dx
  3402 00003F0D 20D2                <1> 	and	dl, dl
  3403                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3404 00003F0F 7403                <1> 	jz	short sysopen_2
  3405                              <1>         	; beq op1 / is open for read op1
  3406                              <1> sysopen_1: ;op0:
  3407 00003F11 66F7D8              <1> 	neg	ax
  3408                              <1>         	; neg r1 
  3409                              <1> 		     ;/ make i-number positive if open for writing [???]
  3410                              <1> 	;; NOTE: iopen always make i-number positive.
  3411                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3412                              <1> sysopen_2: ;op1:
  3413 00003F14 31F6                <1>         xor     esi, esi
  3414                              <1>         	; clr r2 / clear registers
  3415 00003F16 31DB                <1>         xor     ebx, ebx
  3416                              <1> 		; clr r3
  3417                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3418 00003F18 389E[FE6E0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3419                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3420 00003F1E 7625                <1>         jna	short sysopen_4
  3421                              <1> 		; beq 1f / if byte in list is 0 branch
  3422 00003F20 46                  <1>         inc     esi
  3423                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3424 00003F21 6683FE0A            <1>         cmp     si, 10
  3425                              <1> 		; cmp r2,$10. / reached end of list?
  3426 00003F25 72F1                <1> 	jb	short sysopen_3
  3427                              <1> 		; blt 1b / no, go back
  3428                              <1> toomanyf:
  3429                              <1> 	; 14/05/2015
  3430 00003F27 C705[476F0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3430 00003F2F 0000                <1>
  3431 00003F31 E9EDFBFFFF          <1> 	jmp	error
  3432                              <1>         	; br error2 / yes, error (no files open)
  3433                              <1> fnotfound: 
  3434                              <1> 	; 14/05/2015
  3435 00003F36 C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3435 00003F3E 0000                <1>
  3436 00003F40 E9DEFBFFFF          <1> 	jmp	error
  3437                              <1> 
  3438                              <1> sysopen_4: ; 1:
  3439 00003F45 6683BB[C66C0000]00  <1>         cmp     word [ebx+fsp], 0
  3440                              <1> 		; tst fsp(r3) / scan fsp entries
  3441 00003F4D 7610                <1>         jna     short sysopen_5
  3442                              <1> 		; beq 1f / if 0 branch
  3443                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3444 00003F4F 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3445                              <1> 		; add $8.,r3 / add 8 to r3 
  3446                              <1> 			; / to bump it to next entry mfsp table
  3447 00003F53 6681FBF401          <1>         cmp     bx, nfiles*10
  3448                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3449 00003F58 72EB                <1> 	jb	short sysopen_4
  3450                              <1>        		; blt 1b / no, back
  3451 00003F5A E9C4FBFFFF          <1> 	jmp	error
  3452                              <1>         	; br error2 / yes, error
  3453                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3454 00003F5F 668983[C66C0000]    <1>         mov     [ebx+fsp], ax
  3455                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3456                              <1> 			; / into next available entry in fsp table,
  3457                              <1> 	; 12/02/2022
  3458                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3459                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3460                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3461                              <1> 	;xor	edi, edi
  3462                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3463                              <1> 	;	; clr fsp+4(r3)
  3464                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3465                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3466 00003F66 31C0                <1> 	xor	eax, eax
  3467 00003F68 8983[CA6C0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3468 00003F6E 668983[CE6C0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3469                              <1> 
  3470 00003F75 66A1[DE6E0000]      <1> 	mov	ax, [cdev]
  3471 00003F7B 668983[C86C0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3472                              <1> 
  3473 00003F82 89D8                <1>   	mov	eax, ebx
  3474 00003F84 B30A                <1> 	mov	bl, 10
  3475 00003F86 F6F3                <1> 	div	bl 
  3476                              <1> 		; asr r3
  3477                              <1> 		; asr r3 / divide by 8 
  3478                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3479 00003F88 FEC0                <1> 	inc	al
  3480                              <1>         	; inc r3 / add 1 to get fsp entry number
  3481 00003F8A 8886[FE6E0000]      <1>         mov     [esi+u.fp], al
  3482                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3483                              <1> 			; / next available slot in u.fp list
  3484 00003F90 8935[F86E0000]      <1>         mov     [u.r0], esi
  3485                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3486                              <1> 			     ; / into r0 loc on stack
  3487 00003F96 E9A8FBFFFF          <1>         jmp	sysret
  3488                              <1> 		; br sysret2
  3489                              <1> 
  3490                              <1> 	;
  3491                              <1> 	; 'fsp' table (10 bytes/entry)
  3492                              <1> 	; bit 15				   bit 0
  3493                              <1> 	; ---|-------------------------------------------
  3494                              <1> 	; r/w|		i-number of open file
  3495                              <1> 	; ---|-------------------------------------------
  3496                              <1> 	;		   device number
  3497                              <1> 	; -----------------------------------------------
  3498                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3499                              <1> 	; -----------------------------------------------
  3500                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3501                              <1> 	; ----------------------|------------------------
  3502                              <1> 	;  flag that says file 	| number of processes
  3503                              <1> 	;   has been deleted	| that have file open 
  3504                              <1> 	; ----------------------|------------------------
  3505                              <1> 	;
  3506                              <1> 
  3507                              <1> syscreat: ; < create file >
  3508                              <1> 	; 12/02/2022
  3509                              <1> 	; 01/02/2022
  3510                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3511                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3512                              <1> 	;
  3513                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3514                              <1> 	; u.namep points to name of the file and mode is put
  3515                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3516                              <1> 	; If the file aready exists, it's mode and owner remain 
  3517                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3518                              <1> 	; did not exist, an i-node is created with the new mode via
  3519                              <1> 	; 'maknod' whether or not the file already existed, it is
  3520                              <1> 	; open for writing. The fsp table is then searched for a free
  3521                              <1> 	; entry. When a free entry is found, proper data is placed
  3522                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3523                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3524                              <1> 	; is put in the user's r0. 			
  3525                              <1> 	;
  3526                              <1> 	; Calling sequence:
  3527                              <1> 	;	syscreate; name; mode
  3528                              <1> 	; Arguments:
  3529                              <1> 	;	name - name of the file to be created
  3530                              <1> 	;	mode - mode of the file to be created
  3531                              <1> 	; Inputs: (arguments)
  3532                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3533                              <1> 	;		   (the file descriptor of new file)
  3534                              <1> 	; ...............................................................
  3535                              <1> 	;				
  3536                              <1> 	; Retro UNIX 8086 v1 modification: 
  3537                              <1> 	;       'syscreate' system call has two arguments; so,
  3538                              <1> 	;	* 1st argument, name is pointed to by BX register
  3539                              <1> 	;	* 2nd argument, mode is in CX register
  3540                              <1> 	;
  3541                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3542                              <1> 	;	to the user with the file descriptor/number 
  3543                              <1> 	;	(index to u.fp list).
  3544                              <1> 	;
  3545                              <1> 	;call	arg2
  3546                              <1> 	; * name - 'u.namep' points to address of file/path name
  3547                              <1> 	;          in the user's program segment ('u.segmnt')
  3548                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3549                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3550                              <1> 	;          which is on top of stack.
  3551                              <1> 	;
  3552                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3553                              <1> 			    ; / on stack
  3554 00003F9B 891D[106F0000]      <1> 	mov	[u.namep], ebx ; file name address
  3555                              <1> 	;push	cx ; mode
  3556                              <1> 	; 01/02/2022
  3557 00003FA1 51                  <1> 	push	ecx ; mode
  3558 00003FA2 E8720A0000          <1> 	call 	namei        	
  3559                              <1> 		; jsr r0,namei / get the i-number
  3560                              <1>         ;and	ax, ax
  3561                              <1> 	;jz	short syscreat_2	       	
  3562 00003FA7 721B                <1> 	jc	short syscreat_2
  3563                              <1> 		; br  2f / if file doesn't exist 2f
  3564                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3565                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3566 00003FA9 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3567                              <1>         ;jb	syscreat_0 ; yes
  3568                              <1> 	; 02/02/2022
  3569 00003FAD 7305                <1> 	jnb	short syscreat_1
  3570 00003FAF E950FFFFFF          <1> 	jmp	syscreat_0
  3571                              <1> syscreat_1:
  3572 00003FB4 66F7D8              <1> 	neg 	ax
  3573                              <1>         	; neg r1 / if file already exists make i-number 
  3574                              <1> 		       ; / negative (open for writing)
  3575 00003FB7 E8AB190000          <1> 	call	iopen
  3576                              <1>         	; jsr r0,iopen /
  3577 00003FBC E84E130000          <1> 	call	itrunc
  3578                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3579                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3580                              <1> 	; 01/02/2022
  3581 00003FC1 59                  <1> 	pop	ecx ; mode
  3582                              <1> 	; 12/02/2022
  3583 00003FC2 EB0E                <1> 	jmp	short syscreat_3
  3584                              <1>         ;jmp	sysopen_1
  3585                              <1>         	; br op0
  3586                              <1> syscreat_2: ; 2: / file doesn't exist
  3587                              <1> 	; 01/02/2022
  3588 00003FC4 58                  <1> 	pop	eax ; mode
  3589                              <1> 	;pop	ax
  3590                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3591 00003FC5 30E4                <1> 	xor	ah, ah	
  3592                              <1>         	; bic $!377,r1 / clear upper byte
  3593 00003FC7 E8150D0000          <1> 	call 	maknod
  3594                              <1>         	; jsr r0,maknod / make an i-node for this file
  3595 00003FCC 66A1[2A6F0000]      <1> 	mov	ax, [u.dirbuf]
  3596                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3597                              <1> 			        ; / for this new file in r1
  3598                              <1> syscreat_3:
  3599 00003FD2 E93AFFFFFF          <1>         jmp     sysopen_1
  3600                              <1>         	; br op0 / open the file
  3601                              <1> 
  3602                              <1> sysmkdir: ; < make directory >
  3603                              <1> 	; 01/02/2022
  3604                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3605                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3606                              <1> 	;
  3607                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3608                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3609                              <1> 	; The special entries '.' and '..' are not present.
  3610                              <1> 	; Errors are indicated if the directory already exists or		
  3611                              <1> 	; user is not the super user. 
  3612                              <1> 	;
  3613                              <1> 	; Calling sequence:
  3614                              <1> 	;	sysmkdir; name; mode
  3615                              <1> 	; Arguments:
  3616                              <1> 	;	name - points to the name of the directory
  3617                              <1> 	;	mode - mode of the directory
  3618                              <1> 	; Inputs: (arguments)
  3619                              <1> 	; Outputs: -
  3620                              <1> 	;    (sets 'directory' flag to 1; 
  3621                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3622                              <1> 	; ...............................................................
  3623                              <1> 	;				
  3624                              <1> 	; Retro UNIX 8086 v1 modification: 
  3625                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3626                              <1> 	;	* 1st argument, name is pointed to by BX register
  3627                              <1> 	;	* 2nd argument, mode is in CX register
  3628                              <1> 		
  3629                              <1> ; / make a directory
  3630                              <1> 	
  3631                              <1> 	;call	arg2
  3632                              <1> 	; * name - 'u.namep' points to address of file/path name
  3633                              <1> 	;          in the user's program segment ('u.segmnt')
  3634                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3635                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3636                              <1> 	;          which is on top of stack.
  3637                              <1> 
  3638                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3639                              <1> 			    ; / on stack
  3640 00003FD7 891D[106F0000]      <1> 	mov	[u.namep], ebx
  3641                              <1> 	;push	cx ; mode
  3642                              <1> 	; 01/02/2022
  3643 00003FDD 51                  <1> 	push	ecx ; mode
  3644 00003FDE E8360A0000          <1> 	call	namei
  3645                              <1>         	; jsr r0,namei / get the i-number
  3646                              <1>         	;     br .+4 / if file not found branch around error
  3647                              <1>         ;xor 	ax, ax
  3648                              <1> 	;jnz	error
  3649 00003FE3 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3650                              <1> 	;jnc	error	
  3651                              <1> 		; br  error2 / directory already exists (error)
  3652 00003FE5 803D[3E6F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3653                              <1>         	;tstb u.uid / is user the super user
  3654                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3655                              <1> 	;;jna	error
  3656                              <1> 	; 01/02/2022 (BugFix)
  3657 00003FEC 7721                <1> 	ja	short dir_access_err
  3658                              <1>         	;bne error2 / no, not allowed
  3659                              <1> 	;pop	ax
  3660                              <1> 	; 01/02/2022
  3661 00003FEE 58                  <1> 	pop	eax ; mode
  3662                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3663 00003FEF 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3664                              <1>         	;bic $!317,r1 / all but su and ex
  3665                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3666 00003FF3 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3667                              <1>         	;bis $40000,r1 / directory flag
  3668 00003FF6 E8E60C0000          <1> 	call	maknod
  3669                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3670                              <1> sysclose_sysret: ; 01/02/2022
  3671 00003FFB E943FBFFFF          <1> 	jmp	sysret
  3672                              <1>         	;br sysret2 /
  3673                              <1> dir_exists:
  3674                              <1> 	; 14/05/2015
  3675 00004000 C705[476F0000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3675 00004008 0000                <1>
  3676 0000400A E914FBFFFF          <1> 	jmp	error
  3677                              <1> dir_access_err:
  3678                              <1> 	; 14/05/2015
  3679 0000400F C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3679 00004017 0000                <1>
  3680 00004019 E905FBFFFF          <1> 	jmp	error
  3681                              <1> 
  3682                              <1> sysclose: ;<close file>
  3683                              <1> 	; 01/02/2022
  3684                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3685                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3686                              <1> 	;
  3687                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3688                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3689                              <1> 	; is put in r1 and 'fclose' is called.
  3690                              <1> 	;
  3691                              <1> 	; Calling sequence:
  3692                              <1> 	;	sysclose
  3693                              <1> 	; Arguments:
  3694                              <1> 	;	-  
  3695                              <1> 	; Inputs: *u.r0 - file descriptor
  3696                              <1> 	; Outputs: -
  3697                              <1> 	; ...............................................................
  3698                              <1> 	;				
  3699                              <1> 	; Retro UNIX 8086 v1 modification:
  3700                              <1> 	;	 The user/application program puts file descriptor
  3701                              <1> 	;        in BX register as 'sysclose' system call argument.
  3702                              <1> 	; 	 (argument transfer method 1)
  3703                              <1> 
  3704                              <1> 	; / close the file
  3705                              <1> 	
  3706 0000401E 89D8                <1> 	mov 	eax, ebx
  3707 00004020 E87E090000          <1> 	call 	fclose
  3708                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3709                              <1> 		; jsr r0,fclose / close the file
  3710                              <1>                	; br error2 / unknown file descriptor
  3711                              <1> 		; br sysret2
  3712                              <1> 	; 14/05/2015
  3713                              <1> 	;jnc	sysret
  3714                              <1> 	; 01/02/2022
  3715 00004025 73D4                <1> 	jnc	short sysclose_sysret
  3716 00004027 C705[476F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3716 0000402F 0000                <1>
  3717 00004031 E9EDFAFFFF          <1> 	jmp	error
  3718                              <1> 
  3719                              <1> sysemt:
  3720                              <1> 	; 23/02/2022
  3721                              <1> 	; 01/02/2022
  3722                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3723                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3724                              <1> 	;
  3725                              <1> 	; Retro UNIX 8086 v1 modification: 
  3726                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3727                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3728                              <1> 	;
  3729                              <1> 	; Retro UNIX 8086 v1 feature only!
  3730                              <1> 	;	Using purpose: Kernel will start without time-out
  3731                              <1> 	;	(internal clock/timer) functionality.
  3732                              <1> 	;	Then etc/init will enable clock/timer for
  3733                              <1> 	;	multi tasking. (Then it will not be disabled again
  3734                              <1> 	;	except hardware reset/restart.)
  3735                              <1> 
  3736 00004036 803D[3E6F0000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3737                              <1> 	;;ja	error
  3738                              <1> 	;ja	badsys ; 14/05/2015
  3739                              <1> 	; 01/02/2022
  3740                              <1> 	;jna	short emt_0
  3741                              <1> 	;jmp	badsys
  3742 0000403D 773A                <1> 	ja	short sysilgins ; jmp badsys
  3743                              <1> emt_0:
  3744 0000403F FA                  <1> 	cli
  3745 00004040 21DB                <1> 	and	ebx, ebx
  3746 00004042 7429                <1> 	jz	short emt_2
  3747                              <1> 	; Enable multi tasking -time sharing-
  3748 00004044 B8[9A4F0000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3749                              <1> 	; 23/02/2022
  3750 00004049 BA[720A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3751                              <1> emt_1:
  3752 0000404E A3[2D070000]        <1> 	mov	[x_timer], eax
  3753                              <1> 	; 23/02/2022 (Temporary)
  3754 00004053 8915[31070000]      <1> 	mov	[x_rtci], edx
  3755 00004059 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3756 0000405B E853020000          <1> 	call	wttyc  ; clear video page
  3757 00004060 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3758 00004062 E84C020000          <1> 	call	wttyc  ; clear video page
  3759                              <1> 	;
  3760 00004067 FB                  <1> 	sti
  3761 00004068 E9D6FAFFFF          <1> 	jmp	sysret
  3762                              <1> emt_2:
  3763                              <1> 	; Disable multi tasking -time sharing-
  3764 0000406D B8[39070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3765                              <1> 	; 23/02/2022
  3766 00004072 BA[790A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3767                              <1> 	;
  3768 00004077 EBD5                <1> 	jmp	short emt_1
  3769                              <1> 
  3770                              <1> 	; Original UNIX v1 'sysemt' routine
  3771                              <1> ;sysemt:
  3772                              <1>         ;
  3773                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3774                              <1> 			 ; / in loc 30
  3775                              <1>         ;cmp    30,$core / was the argument a lower address 
  3776                              <1> 			; / than core
  3777                              <1>         ;blo    1f / yes, rtssym
  3778                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3779                              <1> 			; / and less than "ecore"
  3780                              <1>         ;blo    2f / yes, sysret2
  3781                              <1> ;1:
  3782                              <1>         ;mov    $rtssym,30
  3783                              <1> ;2:
  3784                              <1>         ;br     sysret2
  3785                              <1> 
  3786                              <1> 	; 01/02/2022
  3787                              <1> sysilgins:
  3788                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3789                              <1> 	; 03/06/2013
  3790                              <1> 	; Retro UNIX 8086 v1 modification: 
  3791                              <1> 	;	not a valid system call ! (not in use)
  3792                              <1> 	;
  3793 00004079 E94EFBFFFF          <1> 	jmp	badsys
  3794                              <1> 	;jmp	error
  3795                              <1> 	;;jmp 	sysret
  3796                              <1> 
  3797                              <1> 	; Original UNIX v1 'sysemt' routine
  3798                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3799                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3800                              <1> 			  ;/ put it in loc 8.,
  3801                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3802                              <1> 		       ; / trap address
  3803                              <1>         ;blo    1f / is the address a user core address?  
  3804                              <1> 		; / yes, go to 2f
  3805                              <1>         ;cmp    10,$ecore
  3806                              <1>         ;blo    2f
  3807                              <1> ;1:
  3808                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3809                              <1> 		    ; / instruction trap address for the system
  3810                              <1> ;2:
  3811                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3812                              <1> 
  3813                              <1> sysmdate: ; < change the modification time of a file >
  3814                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3815                              <1> 	;	(ECX input)
  3816                              <1> 	; 01/02/2022
  3817                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3818                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3819                              <1> 	;
  3820                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3821                              <1> 	; file into core. The user is checked if he is the owner 
  3822                              <1> 	; or super user. If he is neither an error occurs.
  3823                              <1> 	; 'setimod' is then called to set the i-node modification
  3824                              <1> 	; byte and the modification time, but the modification time
  3825                              <1> 	; is overwritten by whatever get put on the stack during
  3826                              <1> 	; a 'systime' system call. This calls are restricted to
  3827                              <1> 	; the super user.		
  3828                              <1> 	;
  3829                              <1> 	; Calling sequence:
  3830                              <1> 	;	sysmdate; name
  3831                              <1> 	; Arguments:
  3832                              <1> 	;	name - points to the name of file
  3833                              <1> 	; Inputs: (arguments)
  3834                              <1> 	; Outputs: -
  3835                              <1> 	; ...............................................................
  3836                              <1> 	;				
  3837                              <1> 	; Retro UNIX 8086 v1 modification: 
  3838                              <1> 	;	 The user/application program puts address 
  3839                              <1> 	;	 of the file name in BX register 
  3840                              <1> 	;	 as 'sysmdate' system call argument.
  3841                              <1> 	;
  3842                              <1> ; / change the modification time of a file
  3843                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3844 0000407E 891D[106F0000]      <1>         mov	[u.namep], ebx
  3845                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3846 00004084 890D[906B0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3847 0000408A E88A090000          <1> 	call	namei
  3848                              <1> 		; jsr r0,namei / get its i-number
  3849                              <1> 	;;jc	error       
  3850                              <1> 		; br error2 / no, such file
  3851                              <1> 	;jc	fnotfound ; file not found !
  3852                              <1> 	; 01/02/2022
  3853 0000408F 7305                <1> 	jnc	short mdate_0
  3854 00004091 E9A0FEFFFF          <1> 	jmp	fnotfound
  3855                              <1> mdate_0:
  3856 00004096 E848110000          <1> 	call	iget
  3857                              <1> 		; jsr r0,iget / get i-node into core
  3858 0000409B A0[3E6F0000]        <1> 	mov	al, [u.uid]
  3859 000040A0 3A05[F96B0000]      <1> 	cmp	al, [i.uid]
  3860                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3861 000040A6 7413                <1> 	je	short mdate_1
  3862                              <1>         	; beq 1f / yes
  3863 000040A8 20C0                <1> 	and	al, al
  3864                              <1> 		; tstb u.uid / no, is user the super user
  3865                              <1> 	;jnz	error
  3866                              <1> 		; bne error2 / no, error
  3867 000040AA 740F                <1> 	jz	short mdate_1
  3868 000040AC C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3868 000040B4 0000                <1>
  3869                              <1> sysstty_err:	; 01/02/2022
  3870 000040B6 E968FAFFFF          <1> 	jmp	error
  3871                              <1> mdate_1: ;1:
  3872 000040BB E82D120000          <1> 	call	setimod
  3873                              <1>         	; jsr r0,setimod / fill in modification data,
  3874                              <1> 		               ; / time etc.
  3875 000040C0 BE[906B0000]        <1> 	mov	esi, p_time
  3876 000040C5 BF[106C0000]        <1> 	mov	edi, i.mtim
  3877 000040CA A5                  <1> 	movsd
  3878                              <1> 		; mov 4(sp),i.mtim / move present time to
  3879                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3880 000040CB E973FAFFFF          <1>         jmp	sysret
  3881                              <1> 		; br sysret2
  3882                              <1> 
  3883                              <1> 	; 01/02/2022
  3884                              <1> sysstty_err_s:
  3885 000040D0 880D[F86E0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3886 000040D6 EBDE                <1> 	jmp	short sysstty_err
  3887                              <1> 
  3888                              <1> sysstty: ; < set tty status and mode >
  3889                              <1> 	; 23/02/2022
  3890                              <1> 	; 22/02/2022
  3891                              <1> 	; 02/02/2022
  3892                              <1> 	; 01/02/2022 (clear screen)
  3893                              <1> 	; 17/11/2015
  3894                              <1> 	; 12/11/2015
  3895                              <1> 	; 29/10/2015
  3896                              <1> 	; 17/10/2015
  3897                              <1> 	; 13/10/2015
  3898                              <1> 	; 29/06/2015
  3899                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3900                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3901                              <1> 	;
  3902                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3903                              <1> 	; whose file descriptor is in (u.r0).
  3904                              <1> 	;
  3905                              <1> 	; Calling sequence:
  3906                              <1> 	;	sysstty; arg
  3907                              <1> 	; Arguments:
  3908                              <1> 	;	arg - address of 3 consequitive words that contain
  3909                              <1> 	;	      the source of status data	
  3910                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  3911                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  3912                              <1> 	; ...............................................................
  3913                              <1> 	;	
  3914                              <1> 	; Retro UNIX 8086 v1 modification: 
  3915                              <1> 	;	'sysstty' system call will set the tty
  3916                              <1> 	;	(clear keyboard buffer and set cursor position)
  3917                              <1> 	;	 in following manner:
  3918                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  3919                              <1> 	;
  3920                              <1> 	; Inputs:
  3921                              <1> 	;	BX = 0 --> means
  3922                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  3923                              <1> 	;	      set cursor position for console tty, only 
  3924                              <1> 	;	      CH will be ignored (char. will not be written)	
  3925                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  3926                              <1> 	;	      set console tty for (current) process
  3927                              <1> 	;	      CL = tty number (0 to 9)
  3928                              <1> 	;	      (If CH = 0, character will not be written)
  3929                              <1> 	;          If CH > 0 (CL < FFh)	
  3930                              <1> 	;             CL = tty number (0 to 9)
  3931                              <1> 	;	      CH = character will be written
  3932                              <1> 	;	        at requested cursor position (in DX)	
  3933                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  3934                              <1>   	;		(only tty number 0 to 7) 
  3935                              <1> 	;          DL = communication parameters (for serial ports) 
  3936                              <1> 	;	        (only for COM1 and COM2 serial ports)
  3937                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  3938                              <1> 	;			or set cursor position	
  3939                              <1> 	;	   DH = 0FFh -> DL is not valid
  3940                              <1> 	;		do not set serial port parameters 
  3941                              <1> 	;		or do not set cursor position
  3942                              <1> 	;
  3943                              <1> 	;	BX > 0 --> points to name of tty
  3944                              <1> 	;    	   CH > 0 -->
  3945                              <1> 	;		CH = character will be written in current 
  3946                              <1> 	;            	cursor position (for tty number from 0 to 7)
  3947                              <1> 	;	     	or character will be sent to serial port
  3948                              <1> 	;	     	(for tty number 8 or 9)
  3949                              <1> 	;		CL = color of the character if tty number < 8.
  3950                              <1> 	;    	   CH = 0 --> Do not write a character, 
  3951                              <1> 	;		set mode (tty 8 to 9) or 
  3952                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  3953                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  3954                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  3955                              <1> 	;		(DL is not valid)
  3956                              <1> 	;	   DL = communication parameters 
  3957                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  3958                              <1> 	;
  3959                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  3960                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  3961                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  3962                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  3963                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  3964                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  3965                              <1> 	;
  3966                              <1> 	; Outputs:
  3967                              <1> 	;	cf = 0 -> OK
  3968                              <1> 	;	     AL = tty number (0 to 9)
  3969                              <1> 	;	     AH = line status if tty number is 8 or 9
  3970                              <1> 	;	     AH = process number (of the caller) 	
  3971                              <1> 	;	cf = 1 means error (requested tty is not ready)
  3972                              <1> 	;	     AH = FFh if the tty is locked 
  3973                              <1> 	;		  (owned by another process)
  3974                              <1> 	;	        = process number (of the caller) 
  3975                              <1> 	;		  (if < FFh and tty number < 8)
  3976                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  3977                              <1> 	;	     AH = line status if tty number is 8 or 9
  3978                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  3979                              <1> 	;	
  3980                              <1> 
  3981                              <1> 	; 27/06/2015 (32 bit modifications)
  3982                              <1> 	; 14/01/2014
  3983 000040D8 31C0                <1> 	xor 	eax, eax
  3984 000040DA 6648                <1> 	dec	ax ; 17/10/2015
  3985 000040DC A3[F86E0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  3986                              <1> 	;;;
  3987                              <1> 	; 01/02/2022
  3988 000040E1 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  3989 000040E3 39C2                <1> 	cmp	edx, eax
  3990                              <1> 	;cmp	dx, ax ; 0FFFFh
  3991 000040E5 7521                <1> 	jne	short sysstty_18
  3992                              <1> 	; clear video page
  3993                              <1> 	; (CH must be 0)
  3994 000040E7 08ED                <1> 	or	ch, ch
  3995 000040E9 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  3996 000040EB 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  3997 000040EE 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  3998 000040F0 20C9                <1> 	and	cl, cl
  3999 000040F2 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4000 000040F4 0FB635[416F0000]    <1> 	movzx	esi, byte [u.uno]
  4001 000040FB 8A8E[556C0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4002 00004101 80F907              <1> 	cmp	cl, 7
  4003 00004104 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4004                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4005 00004106 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4006                              <1> sysstty_18:
  4007 00004108 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4008                              <1> 	; cl = video page (tty) number		
  4009                              <1> 	;;;
  4010 0000410A 21DB                <1> 	and	ebx, ebx
  4011                              <1> 	;jnz	sysstty_6
  4012                              <1> 	; 01/02/2022
  4013 0000410C 7405                <1> 	jz	short sysstty_19
  4014 0000410E E9C2000000          <1> 	jmp	sysstty_6
  4015                              <1> sysstty_19:
  4016                              <1> 	; set console tty
  4017                              <1> 	; 29/10/2015
  4018                              <1> 	; 17/01/2014 
  4019 00004113 80F909              <1> 	cmp	cl, 9
  4020 00004116 7613                <1> 	jna	short sysstty_0
  4021                              <1> 	; 17/11/2015
  4022 00004118 80F9FF              <1> 	cmp	cl, 0FFh
  4023 0000411B 7202                <1> 	jb	short sysstty_13
  4024 0000411D 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4025                              <1> sysstty_13:
  4026 0000411F 8A1D[416F0000]      <1> 	mov	bl, [u.uno] ; process number
  4027 00004125 8A8B[556C0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4028                              <1> sysstty_0:
  4029                              <1> 	; 29/06/2015
  4030                              <1> 	;push	dx
  4031                              <1> 	;push	cx
  4032                              <1> 	; 01/02/2022
  4033 0000412B 52                  <1> 	push	edx
  4034 0000412C 51                  <1> 	push	ecx
  4035 0000412D 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4036 0000412F 88C8                <1> 	mov	al, cl
  4037 00004131 A2[F86E0000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4038 00004136 E8C6180000          <1> 	call	ottyp
  4039                              <1> 	; 01/02/2022
  4040 0000413B 59                  <1> 	pop	ecx
  4041 0000413C 5A                  <1> 	pop	edx
  4042                              <1> 	;pop	cx
  4043                              <1> 	;pop	dx
  4044                              <1> 	;
  4045 0000413D 7220                <1> 	jc	short sysstty_pd_err
  4046                              <1> 	;
  4047                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4048                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4049                              <1> 	;
  4050 0000413F 80F908              <1> 	cmp	cl, 8
  4051 00004142 720C                <1> 	jb	short sysstty_2
  4052                              <1> 	;
  4053 00004144 80FEFF              <1> 	cmp	dh, 0FFh
  4054 00004147 7407                <1> 	je	short sysstty_2
  4055                              <1> 		; set communication parameters for serial ports
  4056                              <1> 
  4057                              <1> ; 01/02/2022
  4058                              <1> ;	; 29/10/2015
  4059                              <1> ;	mov	ah, dl ; communication parameters
  4060                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4061                              <1> ;		;			 THRE int + RDA int 
  4062                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4063                              <1> ;		;			 THRE int + RDA int 
  4064                              <1> ;	sub	al, al ; 0
  4065                              <1> ;	; 12/07/2014
  4066                              <1> ;	cmp	cl, 9
  4067                              <1> ;	jb	short sysstty_1
  4068                              <1> ;	inc	al
  4069                              <1> ;sysstty_1:
  4070                              <1> ;	; 01/02/2022
  4071                              <1> ;	push	ecx
  4072                              <1> ;	;push	cx
  4073                              <1> ;	; 29/06/2015	
  4074                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4075                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4076                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4077                              <1> ;	; 01/02/2022
  4078                              <1> ;	pop	ecx	
  4079                              <1> ;	;pop	cx
  4080                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4081                              <1> 
  4082                              <1> 	; 01/02/2022
  4083 00004149 E832010000          <1> 	call	sysstty_scp
  4084 0000414E 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4085                              <1> 
  4086                              <1> sysstty_2:
  4087                              <1> 	; 17/01/2014
  4088 00004150 20ED                <1> 	and	ch, ch 	; set cursor position 
  4089                              <1> 			; or comm. parameters ONLY
  4090 00004152 7527                <1> 	jnz	short sysstty_3
  4091                              <1> 	; 01/02/2022
  4092 00004154 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4093 00004158 7214                <1> 	jb	short sysstty_20
  4094                              <1> 	; clear screen (video page)
  4095 0000415A E93D010000          <1> 	jmp	sysstty_14
  4096                              <1> 
  4097                              <1> sysstty_pd_err: ; 29/06/2015
  4098                              <1> 	; 'permission denied !' error
  4099 0000415F C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4099 00004167 0000                <1>
  4100 00004169 E9B5F9FFFF          <1> 	jmp	error
  4101                              <1> 
  4102                              <1> sysstty_20:
  4103 0000416E 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4104 00004175 888B[556C0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4105                              <1> sysstty_3:
  4106                              <1> 	; 16/01/2014
  4107 0000417B 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4108                              <1> 	; 17/11/2015
  4109 0000417D B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4110 0000417F 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4111                              <1> 	;jna	sysstty_9
  4112                              <1> 	; 01/02/2022
  4113 00004181 7705                <1> 	ja	short sysstty_12
  4114 00004183 E9C7000000          <1> 	jmp	sysstty_9
  4115                              <1> 
  4116                              <1> sysstty_12:
  4117                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4118                              <1> 	; (Set specified serial port as console tty port)
  4119                              <1> 	; CH = character to be written
  4120                              <1> 	; 15/04/2014
  4121                              <1> 	; CH = 0 --> initialization only
  4122                              <1> 	; AL = character
  4123                              <1> 	; 26/06/2014
  4124 00004188 880D[466F0000]      <1> 	mov	[u.ttyn], cl
  4125                              <1> 	; 12/07/2014
  4126 0000418E 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4127                              <1> 	; 02/02/2022
  4128 00004190 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4129 00004192 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4130 00004194 FEC8                <1> 	dec	al  ; 1 -> 0	
  4131                              <1> 	;and	al, al
  4132 00004196 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4133                              <1>  	; 04/07/2014
  4134 00004198 E8A41E0000          <1> 	call 	sndc
  4135                              <1> 	; 12/07/2014
  4136 0000419D EB0C                <1> 	jmp	short sysstty_5
  4137                              <1> 
  4138                              <1> sysstty_4:
  4139                              <1> 	; 12/07/2014
  4140                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4141 0000419F 88E0                <1> 	mov	al, ah ; 29/06/2015
  4142 000041A1 2C08                <1> 	sub	al, 8
  4143                              <1> 	; 27/06/2015
  4144 000041A3 E81DF4FFFF          <1> 	call	sp_status ; get serial port status
  4145                              <1> 	; AL = Line status, AH = Modem status
  4146                              <1> 	; 12/11/2015
  4147 000041A8 3C80                <1> 	cmp	al, 80h
  4148 000041AA F5                  <1> 	cmc
  4149                              <1> sysstty_5:
  4150 000041AB 66A3[F96E0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4151                              <1> 		; EAX bits 16-23 = modem status	
  4152 000041B1 9C                  <1> 	pushf
  4153 000041B2 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4154 000041B4 A0[466F0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4155 000041B9 E86A190000          <1> 	call	cttyp
  4156 000041BE 9D                  <1> 	popf
  4157                              <1> 	;jnc	sysret ; time out error 
  4158                              <1> 	; 01/02/2022
  4159 000041BF 7205                <1> 	jc	short sysstty_tmout_err
  4160 000041C1 E97DF9FFFF          <1> 	jmp	sysret
  4161                              <1> 
  4162                              <1> sysstty_tmout_err:
  4163 000041C6 C705[476F0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4163 000041CE 0000                <1>
  4164 000041D0 E94EF9FFFF          <1> 	jmp	error
  4165                              <1> 
  4166                              <1> sysstty_6:
  4167                              <1> 	;push	dx
  4168                              <1> 	;push	cx
  4169                              <1> 	; 01/02/2022
  4170 000041D5 52                  <1> 	push	edx
  4171 000041D6 51                  <1> 	push	ecx
  4172 000041D7 891D[106F0000]      <1> 	mov	[u.namep], ebx
  4173 000041DD E837080000          <1> 	call	namei
  4174                              <1> 	; 01/02/2022
  4175 000041E2 59                  <1> 	pop	ecx
  4176 000041E3 5A                  <1> 	pop	edx
  4177                              <1> 	;pop	cx
  4178                              <1> 	;pop	dx
  4179 000041E4 725A                <1> 	jc	short sysstty_inv_dn
  4180                              <1> 	;
  4181 000041E6 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4182 000041EA 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4183                              <1> 	;
  4184 000041EC 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4185                              <1> 		       ; /dev/COM1, /dev/COM2
  4186 000041EE 7206                <1> 	jb	short sysstty_7
  4187 000041F0 2C0A                <1> 	sub	al, 10
  4188                              <1> 	; al = 0 to 9
  4189 000041F2 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4190 000041F4 EB11                <1> 	jmp	short sysstty_8
  4191                              <1> 
  4192                              <1> sysstty_7:
  4193 000041F6 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4194 000041F8 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4195 000041FA 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4196 00004201 8A83[556C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4197                              <1> sysstty_8:
  4198                              <1> 	; 22/02/2022
  4199                              <1> 	; (ebx < 256)
  4200 00004207 A2[F86E0000]        <1> 	mov	[u.r0], al
  4201                              <1> 	; 01/02/2022
  4202                              <1> 	;push	dx
  4203                              <1> 	;push	ax
  4204                              <1> 	;push	cx
  4205 0000420C 52                  <1> 	push	edx
  4206 0000420D 50                  <1> 	push	eax
  4207 0000420E 51                  <1> 	push	ecx
  4208 0000420F E8ED170000          <1> 	call	ottyp
  4209 00004214 59                  <1> 	pop	ecx
  4210 00004215 58                  <1> 	pop	eax
  4211 00004216 5A                  <1> 	pop	edx
  4212                              <1> 	;pop	cx
  4213                              <1> 	;pop	ax
  4214                              <1> 	;pop	dx
  4215                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4216                              <1> 	; 01/02/2022
  4217 00004217 7305                <1> 	jnc	short sysstty_21
  4218 00004219 E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4219                              <1> sysstty_21:
  4220                              <1> 	; 29/10/2015
  4221 0000421E 86E9                <1> 	xchg 	ch, cl
  4222                              <1> 		; cl = character, ch = color code
  4223 00004220 86C1                <1> 	xchg	al, cl
  4224                              <1> 		; al = character, cl = tty number
  4225 00004222 80F907              <1> 	cmp	cl, 7
  4226                              <1> 	;ja	sysstty_12
  4227                              <1> 	; 01/02/2022
  4228 00004225 7628                <1> 	jna	short sysstty_16
  4229                              <1> ;;
  4230 00004227 80FEFF              <1> 	cmp	dh, 0FFh
  4231 0000422A 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4232                              <1> 
  4233                              <1> ; 01/02/2022
  4234                              <1> ;	; 29/10/2015
  4235                              <1> ;	mov	ah, dl ; communication parameters
  4236                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4237                              <1> ;		;			 THRE int + RDA int 
  4238                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4239                              <1> ;		;			 THRE int + RDA int 
  4240                              <1> ;	sub	al, al ; 0
  4241                              <1> ;	; 12/07/2014
  4242                              <1> ;	cmp	cl, 9
  4243                              <1> ;	jb	short sysstty_1
  4244                              <1> ;	inc	al
  4245                              <1> ;sysstty_1:
  4246                              <1> ;	; 01/02/2022
  4247                              <1> ;	push	ecx
  4248                              <1> ;	;push	cx
  4249                              <1> ;	; 29/06/2015	
  4250                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4251                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4252                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4253                              <1> ;	; 01/02/2022
  4254                              <1> ;	pop	ecx	
  4255                              <1> ;	;pop	cx
  4256                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4257                              <1> 
  4258                              <1> 	; 02/02/2022
  4259 0000422C 88C5                <1> 	mov	ch, al ; save char
  4260                              <1> 	; 01/02/2022
  4261 0000422E E84D000000          <1> 	call	sysstty_scp
  4262 00004233 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4263                              <1> 	; 02/02/2022
  4264 00004235 88E8                <1> 	mov	al, ch ; restore char
  4265                              <1> sysstty_22:
  4266                              <1> 	; 01/02/2022
  4267 00004237 08ED                <1> 	or	ch, ch
  4268 00004239 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4269                              <1> 	; send char to (serial port) terminal
  4270                              <1> 	; al = character
  4271                              <1> 	; cl = tty number (8 or 9)
  4272 0000423B E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4273                              <1> 
  4274                              <1> sysstty_inv_dn: 
  4275                              <1> 	; 27/06/2015
  4276                              <1> 	; Invalid device name (not a tty) ! error
  4277                              <1> 	; (Device is not a tty or device name not found)
  4278 00004240 C705[476F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4278 00004248 0000                <1>
  4279 0000424A E9D4F8FFFF          <1> 	jmp	error 
  4280                              <1> 
  4281                              <1> sysstty_16:
  4282                              <1> 	; 22/02/2022
  4283                              <1> 	; 16/01/2014
  4284                              <1> 	;xor	bh, bh
  4285                              <1> sysstty_9: 	; tty 0 to tty 7
  4286                              <1> 	; al = character
  4287                              <1> 	; ch = color/attribute ; 01/02/2022
  4288                              <1> 	;
  4289                              <1>  	; 22/02/2022 (BugFix)
  4290                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4291 0000424F 29DB                <1> 	sub	ebx, ebx ; *
  4292 00004251 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4293                              <1> 	;
  4294 00004253 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4295 00004256 7409                <1> 	je	short sysstty_10
  4296                              <1> 	; 02/02/2022
  4297 00004258 51                  <1> 	push	ecx
  4298 00004259 50                  <1> 	push	eax
  4299                              <1> 	;push	cx
  4300                              <1> 	;push	ax	
  4301                              <1> 	; 22/02/2022	
  4302                              <1> 	;;movzx	ebx, cl ; *
  4303                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4304 0000425A E89ED2FFFF          <1> 	call	set_cpos
  4305                              <1> 	;pop	ax
  4306                              <1> 	;pop	cx
  4307                              <1> 	; 02/02/2022
  4308 0000425F 58                  <1> 	pop	eax
  4309 00004260 59                  <1> 	pop	ecx
  4310                              <1> sysstty_10: 
  4311                              <1> 	; 29/10/2015
  4312 00004261 08C0                <1> 	or	al, al ; character
  4313 00004263 740D                <1> 	jz      short sysstty_11 ; al = 0
  4314                              <1> 	; 17/11/2015
  4315 00004265 3CFF                <1> 	cmp	al, 0FFh
  4316 00004267 7309                <1> 	jnb	short sysstty_11
  4317                              <1> 		; ch > 0 and ch < FFh
  4318                              <1> 	; write a character at current cursor position
  4319 00004269 88EC                <1> 	mov	ah, ch ; color/attribute
  4320                              <1> 	; 12/07/2014
  4321                              <1> 	;push	cx
  4322                              <1> 	; 02/02/2022
  4323 0000426B 51                  <1> 	push	ecx
  4324 0000426C E878D3FFFF          <1> 	call	write_c_current
  4325                              <1> 	;pop	cx
  4326                              <1> 	; 02/02/2022
  4327 00004271 59                  <1> 	pop	ecx
  4328                              <1> sysstty_11:
  4329                              <1> 	; 14/01/2014
  4330 00004272 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4331                              <1> 	; 18/01/2014
  4332                              <1> 	;movzx	eax, cl ; 27/06/2015
  4333 00004274 88C8                <1> 	mov	al, cl
  4334 00004276 E8AD180000          <1> 	call	cttyp
  4335 0000427B E9C3F8FFFF          <1> 	jmp	sysret
  4336                              <1> 
  4337                              <1> sysstty_scp:
  4338                              <1> 	; 02/02/2022
  4339                              <1> 	; set communication parameters (for COM1 or COM2)
  4340                              <1> 	; 01/02/2022
  4341                              <1> 	;
  4342                              <1> 	; 29/10/2015
  4343 00004280 88D4                <1> 	mov	ah, dl ; communication parameters
  4344                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4345                              <1> 		;			 THRE int + RDA int 
  4346                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4347                              <1> 		;			 THRE int + RDA int 
  4348 00004282 28C0                <1> 	sub	al, al ; 0
  4349                              <1> 	; 12/07/2014
  4350 00004284 80F909              <1> 	cmp	cl, 9
  4351 00004287 7202                <1> 	jb	short sysstty_1
  4352 00004289 FEC0                <1> 	inc	al
  4353                              <1> sysstty_1:
  4354                              <1> 	; 02/02/2022
  4355 0000428B 52                  <1> 	push	edx
  4356                              <1> 	; 01/02/2022
  4357 0000428C 51                  <1> 	push	ecx
  4358                              <1> 	;push	cx
  4359                              <1> 	; 29/06/2015	
  4360 0000428D E83BF3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4361 00004292 66890D[F96E0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4362                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4363                              <1> 	; 01/02/2022
  4364 00004299 59                  <1> 	pop	ecx	
  4365                              <1> 	;pop	cx
  4366 0000429A 5A                  <1> 	pop	edx ; 02/02/2022
  4367                              <1> 	; 01/02/2022
  4368                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4369 0000429B C3                  <1> 	retn
  4370                              <1> 
  4371                              <1> sysstty_14:
  4372                              <1> 	; 23/02/2022
  4373                              <1> 	; 02/02/2022
  4374                              <1> 	; ch = 0
  4375                              <1> 	; cl = video page
  4376                              <1> 	;
  4377                              <1> 	; dx = 0FFFFh
  4378                              <1> 	; clear screen (video page)
  4379                              <1> 	;
  4380                              <1> 
  4381                              <1> 	; 02/02/2022
  4382                              <1> 	; clear screen
  4383                              <1> 	;
  4384                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4385                              <1> 
  4386                              <1> 	; 23/02/2022
  4387 0000429C 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4388                              <1> 
  4389                              <1> 	; clear video page
  4390 0000429E E810000000          <1> 	call	wttyc ; 23/02/2022
  4391                              <1> 
  4392                              <1> 	; 23/02/2022
  4393 000042A3 88D8                <1> 	mov	al, bl
  4394 000042A5 8A25[416F0000]      <1> 	mov	ah, [u.uno]
  4395 000042AB 66A3[F86E0000]      <1> 	mov	[u.r0], ax
  4396 000042B1 EBBF                <1> 	jmp	short sysstty_11
  4397                              <1> 
  4398                              <1> wttyc:
  4399                              <1> 	; 23/02/2022
  4400                              <1> 	; (clear video page)
  4401                              <1> 	; INPUT:
  4402                              <1> 	;  bl = video page (0 to 7)
  4403                              <1> 	;
  4404                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4405                              <1> 
  4406                              <1> 	;xor	dx, dx ; column 0, row 0
  4407                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4408                              <1> 	;
  4409                              <1> ;	movzx	ebx, cl
  4410                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4411                              <1> 
  4412                              <1> ;	shl 	bl, 1 
  4413                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4414                              <1> ;		; AL = lock value (0 or process number)
  4415                              <1> ;	or	al, al
  4416                              <1> ;	jz	short @f
  4417                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4418                              <1> ;	jne	short sysstty_15
  4419                              <1> ;		; only the owner can clear its video page
  4420                              <1> ;	xor	al, al ; 0
  4421                              <1> ;@@:
  4422                              <1> ;	;mov	bl, cl		
  4423                              <1> ;	shr	bl, 1 
  4424                              <1> 
  4425 000042B3 30C0                <1> 	xor	al, al	; 0
  4426 000042B5 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4427                              <1> 
  4428                              <1> 	; scroll_up input:
  4429                              <1> 	;
  4430                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4431                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4432                              <1> 	; ah = attribute to be used on blanked line
  4433                              <1> 	; bl = video page number (0 to 7)
  4434                              <1> 
  4435 000042B7 E8CBD2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4436                              <1> 
  4437                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4438                              <1> 
  4439                              <1> 	; bl = video page number (0 to 7)
  4440                              <1> 	;xor	dx, dx ; column 0, row 0
  4441                              <1> 	; 02/02/2022
  4442 000042BC 31D2                <1> 	xor	edx, edx
  4443                              <1> 	; 23/02/2022
  4444                              <1> 	;call	set_cpos
  4445                              <1> 	;retn
  4446 000042BE E93AD2FFFF          <1> 	jmp	set_cpos
  4447                              <1> 
  4448                              <1> 	;mov	al, bl
  4449                              <1> 	;mov	ah, [u.uno]
  4450                              <1> 	;mov	[u.r0], ax
  4451                              <1> 	;jmp	short sysstty_11
  4452                              <1> 
  4453                              <1> ;sysstty_15:
  4454                              <1> ;	; 30/01/2022
  4455                              <1> ;	; permission (denied) error
  4456                              <1> ;	;xor	dl, dl ; sysstty call sign
  4457                              <1> ;	mov	al, cl
  4458                              <1> ;	sub	ah, ah ; 0
  4459                              <1> ;	call	cttyp
  4460                              <1> ;	jmp	error
  4461                              <1> 
  4462                              <1> ; Original UNIX v1 'sysstty' routine:
  4463                              <1> ; gtty:
  4464                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4465                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4466                              <1> 	; 		/ r2 has source
  4467                              <1>         ;mov    r2,-(sp)
  4468                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4469                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4470                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4471                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4472                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4473                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4474                              <1>         ;       br .+4 / list empty, skip branch
  4475                              <1>         ;br     1b / get another character until list is empty
  4476                              <1>         ;mov    0b,r1 / move cc offset to r1
  4477                              <1>         ;inc    r1 / bump it for output clist
  4478                              <1>         ;tstb   cc(r1) / is it 0
  4479                              <1>         ;beq    1f / yes, no characters to output
  4480                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4481                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4482                              <1>         ;br     1b / try to calm it down again
  4483                              <1> ;1:
  4484                              <1>         ;mov    (sp)+,r1
  4485                              <1>         ;mov    (sp)+,r2 / restore registers
  4486                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4487                              <1>         ;beq    1f / if 0, 1f
  4488                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4489                              <1>         ;                   / control status register
  4490                              <1> ;1:
  4491                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4492                              <1>         ;beq    1f / if 0 1f
  4493                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4494                              <1> 	;		    / control status reg
  4495                              <1> ;1:
  4496                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4497                              <1>         ;jmp	sysret2 / return to user
  4498                              <1> 
  4499                              <1> sysgtty: ; < get tty status >
  4500                              <1> 	; 22/02/2022
  4501                              <1> 	; 01/02/2022
  4502                              <1> 	; 23/11/2015
  4503                              <1> 	; 29/10/2015
  4504                              <1> 	; 17/10/2015
  4505                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4506                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4507                              <1> 	;
  4508                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4509                              <1> 	; It stores in the three words addressed by it's argument
  4510                              <1> 	; the status of the typewriter whose file descriptor
  4511                              <1> 	; in (u.r0).
  4512                              <1> 	;
  4513                              <1> 	; Calling sequence:
  4514                              <1> 	;	sysgtty; arg
  4515                              <1> 	; Arguments:
  4516                              <1> 	;	arg - address of 3 words destination of the status
  4517                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4518                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4519                              <1> 	; ...............................................................
  4520                              <1> 	;	
  4521                              <1> 	; Retro UNIX 8086 v1 modification: 
  4522                              <1> 	;	'sysgtty' system call will return status of tty
  4523                              <1> 	;	(keyboard, serial port and video page status)
  4524                              <1> 	;	 in following manner:
  4525                              <1> 	;
  4526                              <1> 	; Inputs:
  4527                              <1> 	;	BX = 0 --> means 
  4528                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4529                              <1> 	;	                 for (current) process
  4530                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4531                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4532                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4533                              <1> 	;	     CH > 0 -->	tty number + 1
  4534                              <1> 	;
  4535                              <1> 	;	BX > 0 --> points to name of tty
  4536                              <1> 	;	     CL = 0 --> return keyboard status
  4537                              <1> 	;	     CL = 1 --> return video page status
  4538                              <1> 	;	     CH = undefined		 
  4539                              <1> 	;
  4540                              <1> 	; Outputs:
  4541                              <1> 	;	cf = 0 ->
  4542                              <1> 	;
  4543                              <1> 	;	     AL = tty number from 0 to 9
  4544                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4545                              <1> 	;	     AH = 0 if the tty is free/unused
  4546                              <1> 	;	     AH = the process number of the caller 
  4547                              <1>  	;	     AH = FFh if the tty is locked by another process
  4548                              <1> 	;
  4549                              <1> 	;	  (if calling is for serial port status)
  4550                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4551                              <1> 	;		  (BH = modem status, BL = Line status)
  4552                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4553                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4554                              <1> 	;
  4555                              <1> 	;	  (if calling is for keyboard status)
  4556                              <1> 	;	     BX = current character in tty/keyboard buffer
  4557                              <1> 	;		  (BH = scan code, BL = ascii code)
  4558                              <1> 	;		  (BX=0 if there is not a waiting character)
  4559                              <1> 	;	     CX  is undefined
  4560                              <1> 	;
  4561                              <1> 	;	  (if calling is for video page status)	
  4562                              <1> 	;	     BX = cursor position on the video page
  4563                              <1> 	;		  if tty number < 8
  4564                              <1> 	;		  (BH = row, BL = column)
  4565                              <1> 	;	     CX = current character (in cursor position)
  4566                              <1> 	;		  on the video page of the tty 
  4567                              <1> 	;		  if tty number < 8
  4568                              <1> 	;		  (CH = color, CL = character)
  4569                              <1> 	;	
  4570                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4571                              <1> 	;
  4572                              <1> 	;	     AH = FFh if the caller is not owner of
  4573                              <1> 	;		  specified tty or console tty
  4574                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4575                              <1> 	;	     BX, CX are undefined if cf = 1
  4576                              <1> 	;
  4577                              <1> 	;	  (If tty number is 8 or 9)
  4578                              <1> 	;	     AL = tty number 
  4579                              <1> 	;	     AH = the process number of the caller 
  4580                              <1> 	;	     BX = serial port status
  4581                              <1> 	;  		 (BH = modem status, BL = Line status)
  4582                              <1> 	;	     CX = 0
  4583                              <1> 	;
  4584                              <1> 		
  4585                              <1> gtty:   ; get (requested) tty number
  4586                              <1> 	; 22/02/2022
  4587                              <1> 	; 01/02/2022
  4588                              <1> 	; 17/10/2015
  4589                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4590                              <1> 	; 30/05/2013 - 12/07/2014
  4591                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4592                              <1> 	;
  4593                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4594                              <1> 	;
  4595                              <1> 	; 28/06/2015 (32 bit modifications)
  4596                              <1> 	; 16/01/2014
  4597 000042C3 31C0                <1> 	xor 	eax, eax
  4598 000042C5 6648                <1> 	dec	ax ; 17/10/2015
  4599 000042C7 A3[F86E0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4600 000042CC 80F901              <1> 	cmp	cl, 1
  4601 000042CF 760F                <1> 	jna	short sysgtty_0
  4602                              <1> sysgtty_invp:
  4603                              <1> 	; 28/06/2015
  4604 000042D1 C705[476F0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4604 000042D9 0000                <1>
  4605 000042DB E943F8FFFF          <1> 	jmp	error
  4606                              <1> sysgtty_0:	
  4607 000042E0 21DB                <1> 	and	ebx, ebx
  4608 000042E2 742E                <1> 	jz	short sysgtty_1
  4609                              <1> 	;
  4610 000042E4 891D[106F0000]      <1> 	mov	[u.namep], ebx
  4611                              <1> 	;push	cx ; 23/11/2015
  4612                              <1> 	; 01/02/2022
  4613 000042EA 51                  <1> 	push	ecx
  4614 000042EB E829070000          <1> 	call	namei
  4615                              <1> 	; 01/02/2022
  4616 000042F0 59                  <1> 	pop	ecx
  4617                              <1> 	;pop	cx ; 23/11/2015
  4618 000042F1 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4619                              <1> 	;
  4620 000042F3 6683F801            <1> 	cmp	ax, 1
  4621 000042F7 7622                <1> 	jna	short sysgtty_2
  4622                              <1> 	; 01/02/2022
  4623 000042F9 20E4                <1> 	and	ah, ah
  4624 000042FB 7506                <1> 	jnz	short sysgtty_inv_dn
  4625                              <1> 	;sub	ax, 10
  4626 000042FD 2C0A                <1> 	sub	al, 10
  4627 000042FF 3C09                <1> 	cmp	al, 9
  4628                              <1> 	;cmp	ax, 9
  4629                              <1> 	;ja	short sysgtty_inv_dn
  4630                              <1> 	;mov	ch, al
  4631                              <1> 	;jmp	short sysgtty_4
  4632                              <1> 	; 23/11/2015
  4633 00004301 7629                <1> 	jna	short sysgtty_4
  4634                              <1> sysgtty_inv_dn: 
  4635                              <1> 	; 28/06/2015
  4636                              <1> 	; Invalid device name (not a tty) ! error
  4637                              <1> 	; (Device is not a tty or device name not found)
  4638 00004303 C705[476F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4638 0000430B 0000                <1>
  4639 0000430D E911F8FFFF          <1> 	jmp	error 
  4640                              <1> sysgtty_1:
  4641                              <1> 	; 16/01/2014
  4642 00004312 80FD0A              <1> 	cmp	ch, 10
  4643 00004315 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4644 00004317 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4645 00004319 790F                <1> 	jns	short sysgtty_3 ; not negative
  4646                              <1> 	;
  4647                              <1> sysgtty_2:
  4648                              <1> 	; get tty number of console tty
  4649 0000431B 8A25[416F0000]      <1> 	mov	ah, [u.uno]
  4650                              <1>  	; 28/06/2015
  4651 00004321 0FB6DC              <1> 	movzx 	ebx, ah
  4652 00004324 8AAB[556C0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4653                              <1> sysgtty_3:
  4654 0000432A 88E8                <1> 	mov	al, ch
  4655                              <1> sysgtty_4:
  4656 0000432C A2[F86E0000]        <1> 	mov	[u.r0], al
  4657                              <1>  	; 28/06/2015
  4658                              <1> 	;cmp	al, 9
  4659                              <1> 	;ja	short sysgtty_invp
  4660 00004331 8B2D[F46E0000]      <1> 	mov	ebp, [u.usp]
  4661                              <1> 	; 23/11/2015
  4662 00004337 20C9                <1> 	and	cl, cl
  4663 00004339 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4664 0000433B 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4665 0000433D 722E                <1> 	jb	short sysgtty_6 ; video page status
  4666                              <1> 	; serial port status
  4667                              <1> 	; 12/07/2014
  4668                              <1> 	;mov	dx, 0
  4669                              <1> 	;je	short sysgtty_5
  4670                              <1> 	;inc	dl
  4671                              <1> ;sysgtty_5:
  4672                              <1> 	; 28/06/2015
  4673 0000433F 2C08                <1> 	sub	al, 8
  4674 00004341 E87FF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4675                              <1> 	; AL = Line status, AH = Modem status
  4676 00004346 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4677 0000434A 8A25[416F0000]      <1> 	mov	ah, [u.uno]
  4678 00004350 8825[F96E0000]      <1>         mov     [u.r0+1], ah
  4679 00004356 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4680                              <1> 				; (in ECX)
  4681 0000435C A880                <1> 	test	al, 80h
  4682 0000435E 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4683 00004360 A801                <1> 	test	al, 1
  4684                              <1> 	;jz	sysret
  4685 00004362 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4686 00004364 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4687                              <1> sysgtty_10:
  4688 00004368 E9D6F7FFFF          <1> 	jmp	sysret
  4689                              <1> sysgtty_6:
  4690 0000436D A2[466F0000]        <1> 	mov	[u.ttyn], al ; tty number
  4691                              <1> 	;movzx	ebx, al
  4692 00004372 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4693 00004374 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4694                              <1> 	; 22/04/2014 - 29/06/2015
  4695 00004376 81C3[946B0000]      <1>         add     ebx, ttyl
  4696 0000437C 8A23                <1>  	mov	ah, [ebx]
  4697 0000437E 3A25[416F0000]      <1> 	cmp	ah, [u.uno]
  4698 00004384 7404                <1> 	je	short sysgtty_7
  4699 00004386 20E4                <1> 	and	ah, ah
  4700                              <1> 	;jz	short sysgtty_7
  4701 00004388 7506                <1> 	jnz	short sysgtty_8
  4702                              <1> 	;mov	ah, 0FFh
  4703                              <1> sysgtty_7:
  4704 0000438A 8825[F96E0000]      <1>         mov     [u.r0+1], ah
  4705                              <1> sysgtty_8:
  4706 00004390 08C9                <1> 	or	cl, cl
  4707 00004392 7510                <1> 	jnz	short sysgtty_9
  4708 00004394 B001                <1> 	mov	al, 1  ; test a key is available
  4709 00004396 E8291C0000          <1> 	call	getc
  4710 0000439B 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4711 0000439F E99FF7FFFF          <1> 	jmp	sysret
  4712                              <1> sysgtty_9:
  4713 000043A4 8A1D[466F0000]      <1> 	mov	bl, [u.ttyn]
  4714                              <1> 	; bl = video page number
  4715 000043AA E8861D0000          <1> 	call 	get_cpos
  4716                              <1> 	; dx = cursor position
  4717 000043AF 66895510            <1> 	mov	[ebp+16], dx ; bx
  4718                              <1> 	;mov	bl, [u.ttyn]
  4719                              <1> 	; bl = video page number
  4720 000043B3 E88E1D0000          <1> 	call	read_ac_current
  4721                              <1> 	; ax = character and attribute/color
  4722 000043B8 66894518            <1> 	mov	[ebp+24], ax ; cx
  4723 000043BC E982F7FFFF          <1> 	jmp	sysret
  4724                              <1> sysgtty_dnr_err:
  4725                              <1> 	; 'device not responding !' error	
  4726                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4727 000043C1 C705[476F0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4727 000043C9 0000                <1>
  4728 000043CB E953F7FFFF          <1> 	jmp	error	
  4729                              <1> 
  4730                              <1> ; Original UNIX v1 'sysgtty' routine:
  4731                              <1> ; sysgtty:
  4732                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4733                              <1> 	;	       / r2 has destination
  4734                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4735                              <1> 	;                     / in 1st word of dest
  4736                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4737                              <1> 	;                     / in 2nd word of dest
  4738                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4739                              <1>         ;jmp    sysret2 / return to user
  4740                              <1> 	
  4741                              <1> ; Original UNIX v1 'gtty' routine:
  4742                              <1> ; gtty:
  4743                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4744                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4745                              <1>         ;jsr    r0,getf / get the i-number of the file
  4746                              <1>         ;tst    r1 / is it open for reading
  4747                              <1>         ;bgt    1f / yes
  4748                              <1>         ;neg    r1 / no, i-number is negative, 
  4749                              <1> 	;          / so make it positive
  4750                              <1> ;1:
  4751                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4752                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4753                              <1>         ;bhis   error9 / no, error
  4754                              <1>         ;asl    r1 / 0%2
  4755                              <1>         ;asl    r1 / 0%4 / yes
  4756                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4757                              <1> 	;	       ; / tty block
  4758                              <1>         ;mov    u.off,r2 / put argument in r2
  4759                              <1>         ;rts    r0 / return
  1990                                  %include 'u2.s'        ; 11/05/2015
  1991                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC
  1992                              <1> ; Last Modification: 12/02/2022
  1993                              <1> ; ----------------------------------------------------------------------------
  1994                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1995                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1996                              <1> ;
  1997                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  1998                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  1999                              <1> ; <Bell Laboratories (17/3/1972)>
  2000                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2001                              <1> ;
  2002                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2003                              <1> ;
  2004                              <1> ; ****************************************************************************
  2005                              <1> ; 03/01/2016
  2006                              <1> 
  2007                              <1> syslink:
  2008                              <1> 	; 03/02/2022
  2009                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2010                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2011                              <1> 	;
  2012                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2013                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2014                              <1> 	; given to the entry that will go in the current directory.
  2015                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2016                              <1> 	; in the name 2 entry of current directory is the same
  2017                              <1> 	; i-number for the name 1 file.
  2018                              <1> 	;
  2019                              <1> 	; Calling sequence:
  2020                              <1> 	;	syslink; name 1; name 2
  2021                              <1> 	; Arguments:
  2022                              <1> 	;	name 1 - file name to which link will be created.
  2023                              <1> 	;	name 2 - name of entry in current directory that
  2024                              <1> 	;		 links to name 1.
  2025                              <1> 	; Inputs: -
  2026                              <1> 	; Outputs: -
  2027                              <1> 	; ...............................................................
  2028                              <1> 	;	
  2029                              <1> 	; Retro UNIX 8086 v1 modification: 
  2030                              <1> 	;       'syslink' system call has two arguments; so,
  2031                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2032                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2033                              <1> 	;
  2034                              <1> 		; / name1, name2
  2035                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2036 000043D0 891D[106F0000]      <1> 	mov	[u.namep], ebx
  2037 000043D6 51                  <1> 	push	ecx
  2038 000043D7 E83D060000          <1> 	call	namei
  2039                              <1> 		; jsr r0,namei / find the i-number associated with
  2040                              <1> 			     ; / the 1st path name
  2041                              <1>      	;;and	ax, ax
  2042                              <1> 	;;jz	error ; File not found
  2043                              <1> 	;jc	error 
  2044                              <1> 		; br error9 / cannot be found
  2045 000043DC 730F                <1> 	jnc	short syslink0
  2046                              <1> 	;pop 	ecx
  2047                              <1> 	; 'file not found !' error
  2048 000043DE C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2048 000043E6 0000                <1>
  2049 000043E8 E936F7FFFF          <1> 	jmp	error
  2050                              <1> syslink0:
  2051 000043ED E8F10D0000          <1> 	call	iget
  2052                              <1> 		; jsr r0,iget / get the i-node into core
  2053 000043F2 8F05[106F0000]      <1> 	pop	dword [u.namep] ; ecx
  2054                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2055                              <1> 	; 03/02/2022
  2056 000043F8 50                  <1> 	push	eax
  2057                              <1> 	;push	ax
  2058                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2059                              <1> 			    ; / (a link to this file is to be created)
  2060 000043F9 66FF35[DE6E0000]    <1> 	push	word [cdev]
  2061                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2062 00004400 E852000000          <1> 	call	isdir
  2063                              <1> 		; jsr r0,isdir / is it a directory
  2064 00004405 E80F060000          <1> 	call	namei
  2065                              <1> 		; jsr r0,namei / no, get i-number of name2
  2066                              <1> 	;jnc	error
  2067                              <1> 		; br .+4   / not found 
  2068                              <1> 			 ; / so r1 = i-number of current directory
  2069                              <1> 			 ; / ii = i-number of current directory
  2070                              <1> 		; br error9 / file already exists., error
  2071 0000440A 720F                <1> 	jc	short syslink1
  2072                              <1> 	; pop ax
  2073                              <1> 	; pop ax
  2074                              <1> 	; 'file exists !' error
  2075 0000440C C705[476F0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2075 00004414 0000                <1>
  2076 00004416 E908F7FFFF          <1> 	jmp	error
  2077                              <1> syslink1:
  2078 0000441B 6659                <1> 	pop	cx
  2079                              <1> 	;cmp	cx, [cdev]
  2080 0000441D 3A0D[DE6E0000]      <1> 	cmp	cl, [cdev]
  2081                              <1> 	;jne	error
  2082                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2083                              <1> 			       ; / end of current directory
  2084                              <1> 	        ; bne error9
  2085 00004423 740F                <1> 	je	short syslink2
  2086                              <1> 	; 'not same drive !' error
  2087 00004425 C705[476F0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2087 0000442D 0000                <1>
  2088 0000442F E9EFF6FFFF          <1> 	jmp	error
  2089                              <1> syslink2:
  2090                              <1> 	;pop	ax
  2091                              <1> 	;push	ax
  2092                              <1> 	; 03/02/2022
  2093                              <1> 	;mov	eax, [esp]
  2094 00004434 58                  <1> 	pop	eax
  2095 00004435 50                  <1> 	push	eax
  2096 00004436 66A3[2A6F0000]      <1> 	mov	[u.dirbuf], ax
  2097                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2098 0000443C E89E000000          <1> 	call	mkdir
  2099                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2100                              <1> 		 	     ; / in current directory
  2101                              <1> 	; 03/02/2022
  2102 00004441 58                  <1> 	pop	eax
  2103                              <1> 	;pop	ax
  2104                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2105 00004442 E89C0D0000          <1> 	call	iget
  2106                              <1> 		; jsr r0,iget / get i-node into core
  2107 00004447 FE05[F86B0000]      <1> 	inc	byte [i.nlks]
  2108                              <1> 		; incb i.nlks / add 1 to its number of links
  2109 0000444D E89B0E0000          <1> 	call	setimod
  2110                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2111 00004452 E9ECF6FFFF          <1> 	jmp	sysret
  2112                              <1> 
  2113                              <1> isdir:
  2114                              <1> 	; 03/02/2022
  2115                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2116                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2117                              <1> 	;
  2118                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2119                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2120                              <1> 	;  called by syslink and sysunlink to make sure directories
  2121                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2122                              <1> 	; 'isdir' does not bother checking. The current i-node
  2123                              <1> 	;  is not disturbed.			
  2124                              <1> 	;		
  2125                              <1> 	; INPUTS ->
  2126                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2127                              <1> 	;    u.uid - user id
  2128                              <1> 	; OUTPUTS ->
  2129                              <1> 	;    r1 - contains current i-number upon exit
  2130                              <1> 	;    	 (current i-node back in core) 
  2131                              <1> 	;	
  2132                              <1> 	; ((AX = R1))
  2133                              <1> 	;
  2134                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2135                              <1> 	;
  2136                              <1> 
  2137                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2138                              <1> 	; / there is an error unless super user made the call
  2139                              <1> 	
  2140 00004457 803D[3E6F0000]00    <1> 	cmp	byte [u.uid], 0 
  2141                              <1> 		; tstb u.uid / super user
  2142 0000445E 762B                <1> 	jna	short isdir1
  2143                              <1> 		; beq 1f / yes, don't care
  2144 00004460 66FF35[DA6E0000]    <1> 	push	word [ii]
  2145                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2146 00004467 E8770D0000          <1> 	call	iget
  2147                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2148                              <1> 	; 03/02/2022
  2149 0000446C F605[F76B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2150                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2151                              <1> 		; bit $40000,i.flgs / is it a directory
  2152                              <1> 	;jnz	error
  2153                              <1> 		; bne error9 / yes, error
  2154 00004473 740F                <1> 	jz	short isdir0
  2155 00004475 C705[476F0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2155 0000447D 0000                <1>
  2156                              <1> 				; 'permission denied !' error
  2157                              <1> 	;pop	ax
  2158 0000447F E99FF6FFFF          <1> 	jmp	error	
  2159                              <1> isdir0:	
  2160 00004484 6658                <1> 	pop	ax
  2161                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2162 00004486 E8580D0000          <1> 	call	iget
  2163                              <1> 		; jsr r0,iget / get it back in
  2164                              <1> isdir1: ; 1:
  2165 0000448B C3                  <1> 	retn
  2166                              <1> 		; rts r0
  2167                              <1> 
  2168                              <1> sysunlink:
  2169                              <1> 	; 03/02/2022
  2170                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2171                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2172                              <1> 	;
  2173                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2174                              <1> 	; name from its directory. If this entry was the last link
  2175                              <1> 	; to the file, the contents of the file are freed and the
  2176                              <1> 	; file is destroyed. If, however, the file was open in any
  2177                              <1> 	; process, the actual destruction is delayed until it is 
  2178                              <1> 	; closed, even though the directory entry has disappeared.
  2179                              <1> 	; 
  2180                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2181                              <1> 	; does not exist or that its directory can not be written.
  2182                              <1> 	; Write permission is not required on the file itself.
  2183                              <1> 	; It is also illegal to unlink a directory (except for
  2184                              <1> 	; the superuser).
  2185                              <1> 	;
  2186                              <1> 	; Calling sequence:
  2187                              <1> 	;	sysunlink; name
  2188                              <1> 	; Arguments:
  2189                              <1> 	;	name - name of directory entry to be removed 
  2190                              <1> 	; Inputs: -
  2191                              <1> 	; Outputs: -
  2192                              <1> 	; ...............................................................
  2193                              <1> 	;				
  2194                              <1> 	; Retro UNIX 8086 v1 modification:
  2195                              <1> 	;	 The user/application program puts address of the name
  2196                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2197                              <1> 
  2198                              <1> 	; / name - remove link name
  2199 0000448C 891D[106F0000]      <1> 	mov	[u.namep], ebx
  2200                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2201 00004492 E882050000          <1> 	call	namei
  2202                              <1> 		; jsr r0,namei / find the i-number associated 
  2203                              <1> 			     ; / with the path name
  2204                              <1> 	;jc	error
  2205                              <1> 		; br error9 / not found
  2206 00004497 730F                <1> 	jnc	short sysunlink1
  2207                              <1> 	; 'file not found !' error
  2208 00004499 C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2208 000044A1 0000                <1>
  2209 000044A3 E97BF6FFFF          <1> 	jmp	error
  2210                              <1> sysunlink1:
  2211                              <1> 	; 03/02/2022
  2212 000044A8 50                  <1> 	push	eax
  2213                              <1> 	;push	ax
  2214                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2215 000044A9 E8A9FFFFFF          <1> 	call	isdir
  2216                              <1> 		; jsr r0,isdir / is it a directory
  2217                              <1> 	;xor 	ax, ax
  2218                              <1> 	; 03/02/2022
  2219 000044AE 31C0                <1> 	xor	eax, eax
  2220 000044B0 66A3[2A6F0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2221                              <1> 		; clr u.dirbuf / no, clear the location that will
  2222                              <1> 			   ; / get written into the i-number portion
  2223                              <1> 			 ; / of the entry
  2224 000044B6 832D[146F0000]0A    <1> 	sub	dword [u.off], 10
  2225                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2226 000044BD E865000000          <1> 	call	wdir
  2227                              <1> 		; jsr r0,wdir / free the directory entry
  2228                              <1> 	; 03/02/2022
  2229 000044C2 58                  <1> 	pop	eax
  2230                              <1> 	;pop	ax
  2231                              <1> 		; mov (sp)+,r1 / get i-number back
  2232 000044C3 E81B0D0000          <1> 	call	iget
  2233                              <1> 		; jsr r0,iget / get i-node
  2234 000044C8 E8200E0000          <1> 	call	setimod
  2235                              <1> 		; jsr r0,setimod / set modified flag
  2236 000044CD FE0D[F86B0000]      <1> 	dec	byte [i.nlks]
  2237                              <1> 		; decb i.nlks / decrement the number of links
  2238                              <1> 	;jnz	sysret
  2239                              <1> 		; bgt sysret9 / if this was not the last link
  2240                              <1> 			    ; / to file return
  2241                              <1> 	; 03/02/2022
  2242 000044D3 7505                <1> 	jnz	short sysunlink2
  2243                              <1> 	; AX = r1 = i-number
  2244 000044D5 E860090000          <1> 	call	anyi
  2245                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2246                              <1> 			 ; / Then free contents of file and destroy it.
  2247                              <1> sysunlink2:
  2248 000044DA E964F6FFFF          <1> 	jmp	sysret
  2249                              <1> 		; br sysret9
  2250                              <1> 
  2251                              <1> mkdir:
  2252                              <1> 	; 03/02/2022
  2253                              <1> 	; 12/10/2015
  2254                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2255                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2256                              <1> 	;
  2257                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2258                              <1> 	; by u.namep into the current directory.
  2259                              <1> 	;
  2260                              <1> 	; INPUTS ->
  2261                              <1> 	;    u.namep - points to a file name 
  2262                              <1> 	;	           that is about to be a directory entry.
  2263                              <1> 	;    ii - current directory's i-number.	
  2264                              <1> 	; OUTPUTS ->
  2265                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2266                              <1> 	;    u.off - points to entry to be filled 
  2267                              <1> 	;	     in the current directory		
  2268                              <1> 	;    u.base - points to start of u.dirbuf.
  2269                              <1> 	;    r1 - contains i-number of current directory 
  2270                              <1> 	;	
  2271                              <1> 	; ((AX = R1)) output
  2272                              <1> 	;
  2273                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2274                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2275                              <1> 	;
  2276                              <1> 
  2277                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2278 000044DF 31C0                <1> 	xor 	eax, eax
  2279 000044E1 BF[2C6F0000]        <1>         mov     edi, u.dirbuf+2
  2280 000044E6 89FE                <1> 	mov	esi, edi
  2281 000044E8 AB                  <1> 	stosd
  2282 000044E9 AB                  <1> 	stosd
  2283                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2284 000044EA 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2285                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2286                              <1> 	;mov 	ebp, [u.namep]
  2287 000044EC E864060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2288                              <1> 		; esi = physical address (page start + offset)
  2289                              <1> 		; ecx = byte count in the page (1 - 4096)
  2290                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2291                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2292                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2293                              <1> mkdir_1: ; 1: 
  2294 000044F1 45                  <1> 	inc	ebp ; 12/10/2015
  2295                              <1> 	;
  2296                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2297                              <1> 	 ; 01/08/2013
  2298 000044F2 AC                  <1> 	lodsb
  2299                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2300 000044F3 20C0                <1> 	and 	al, al
  2301 000044F5 7426                <1> 	jz 	short mkdir_3 	  
  2302                              <1> 		; beq 1f / if null, done
  2303 000044F7 3C2F                <1> 	cmp	al, '/'
  2304                              <1> 		; cmp r1,$'/ / is it a "/"?
  2305 000044F9 7413                <1> 	je	short mkdir_err
  2306                              <1> 	;je	error
  2307                              <1> 		; beq error9 / yes, error
  2308                              <1> 	; 03/02/2022
  2309 000044FB 49                  <1> 	dec	ecx
  2310                              <1> 	; 12/10/2015
  2311                              <1> 	;dec	cx
  2312 000044FC 7505                <1> 	jnz	short mkdir_2
  2313                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2314 000044FE E858060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2315                              <1> 		; esi = physical address (page start + offset)
  2316                              <1> 		; ecx = byte count in the page
  2317                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2318                              <1> mkdir_2:
  2319 00004503 81FF[346F0000]      <1> 	cmp     edi, u.dirbuf+10
  2320                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2321                              <1> 				     ; / a char?
  2322 00004509 74E6                <1> 	je	short mkdir_1
  2323                              <1> 		; beq 1b / yes, go back
  2324 0000450B AA                  <1> 	stosb
  2325                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2326 0000450C EBE3                <1> 	jmp 	short mkdir_1
  2327                              <1> 		; br 1b / get next char
  2328                              <1> mkdir_err:
  2329                              <1> 	; 17/06/2015
  2330 0000450E C705[476F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2330 00004516 0000                <1>
  2331 00004518 E906F6FFFF          <1> 	jmp	error
  2332                              <1> mkdir_3: ; 1:
  2333 0000451D A1[0C6F0000]        <1> 	mov	eax, [u.dirp]
  2334 00004522 A3[146F0000]        <1> 	mov	[u.off], eax
  2335                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2336                              <1> 				 ; / slot to u.off
  2337                              <1> wdir: 	; 03/02/2022
  2338                              <1> 	; 29/04/2013
  2339 00004527 C705[186F0000]-     <1>         mov     dword [u.base], u.dirbuf
  2339 0000452D [2A6F0000]          <1>
  2340                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2341 00004531 C705[1C6F0000]0A00- <1>         mov     dword [u.count], 10
  2341 00004539 0000                <1>
  2342                              <1> 		; mov $10.,u.count / u.count = 10
  2343 0000453B 66A1[DA6E0000]      <1> 	mov	ax, [ii] 
  2344                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2345 00004541 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2346 00004543 E86F0D0000          <1> 	call 	access
  2347                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2348                              <1> 				 ; / for writing
  2349                              <1> 	; AX = i-number of current directory
  2350                              <1> 	; 01/08/2013
  2351 00004548 FE05[596F0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2352                              <1> 	;call	writei
  2353                              <1> 	;	; jsr r0,writei / write into directory
  2354                              <1> 	;retn	
  2355                              <1> 	;	; rts r0
  2356                              <1> 	; 03/02/2022
  2357 0000454E E952100000          <1> 	jmp	writei
  2358                              <1> 
  2359                              <1> sysexec:
  2360                              <1> 	; 03/02/2022
  2361                              <1> 	; 23/10/2015
  2362                              <1> 	; 19/10/2015
  2363                              <1> 	; 10/10/2015, 18/10/2015
  2364                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2365                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2366                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2367                              <1> 	; 24/06/2015, 25/06/2015
  2368                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2369                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2370                              <1> 	;
  2371                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2372                              <1> 	; pointed to by 'name' in the sysexec call. 
  2373                              <1> 	; 'sysexec' performs the following operations:
  2374                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2375                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2376                              <1> 	;    3. sets trap vectors to system routines.
  2377                              <1> 	;    4. loads arguments to be passed to executing file into
  2378                              <1> 	;	highest locations of user's core
  2379                              <1> 	;    5. puts pointers to arguments in locations immediately
  2380                              <1> 	;	following arguments.
  2381                              <1> 	;    6.	saves number of arguments in next location.
  2382                              <1> 	;    7. intializes user's stack area so that all registers
  2383                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2384                              <1> 	;	to core when 'sysret' restores registers 
  2385                              <1> 	;	and does an rti.
  2386                              <1> 	;    8. inializes u.r0 and u.sp
  2387                              <1> 	;    9. zeros user's core down to u.r0
  2388                              <1> 	;   10.	reads executable file from storage device into core
  2389                              <1> 	;	starting at location 'core'.
  2390                              <1> 	;   11.	sets u.break to point to end of user's code with
  2391                              <1> 	;	data area appended.
  2392                              <1> 	;   12.	calls 'sysret' which returns control at location
  2393                              <1> 	;	'core' via 'rti' instruction. 		  		
  2394                              <1> 	;
  2395                              <1> 	; Calling sequence:
  2396                              <1> 	;	sysexec; namep; argp
  2397                              <1> 	; Arguments:
  2398                              <1> 	;	namep - points to pathname of file to be executed
  2399                              <1> 	;	argp  - address of table of argument pointers
  2400                              <1> 	;	argp1... argpn - table of argument pointers
  2401                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2402                              <1> 	; Inputs: (arguments)
  2403                              <1> 	; Outputs: -	
  2404                              <1> 	; ...............................................................
  2405                              <1> 	;
  2406                              <1> 	; Retro UNIX 386 v1 modification: 
  2407                              <1> 	;	User application runs in it's own virtual space 
  2408                              <1> 	;	which is izolated from kernel memory (and other
  2409                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2410                              <1> 	;	privilige mode. Virtual start address is always 0.
  2411                              <1> 	;	User's core memory starts at linear address 400000h
  2412                              <1> 	;	(the end of the 1st 4MB).
  2413                              <1> 	;
  2414                              <1> 	; Retro UNIX 8086 v1 modification: 
  2415                              <1> 	;	user/application segment and system/kernel segment
  2416                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2417                              <1> 	;	are different (user's registers are saved to 
  2418                              <1> 	;	and then restored from system's stack.)
  2419                              <1> 	;
  2420                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2421                              <1> 	;	      arguments which were in these registers;
  2422                              <1> 	;	      but, it returns by putting the 1st argument
  2423                              <1> 	;	      in 'u.namep' and the 2nd argument
  2424                              <1> 	;	      on top of stack. (1st argument is offset of the
  2425                              <1> 	;	      file/path name in the user's program segment.)		 	
  2426                              <1> 	
  2427                              <1> 	;call	arg2
  2428                              <1> 	; * name - 'u.namep' points to address of file/path name
  2429                              <1> 	;          in the user's program segment ('u.segmnt')
  2430                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2431                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2432                              <1> 	;          which is on top of stack.
  2433                              <1> 	;
  2434                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2435                              <1> 
  2436                              <1> 	; 23/06/2015 (32 bit modifications)
  2437                              <1> 
  2438 00004553 891D[106F0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2439                              <1>         ; 18/10/2015
  2440 00004559 890D[706F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2441 0000455F E8B5040000          <1> 	call	namei
  2442                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2443                              <1> 			     ; / named in sysexec call in r1
  2444                              <1> 	;jc	error
  2445                              <1> 		; br error9
  2446 00004564 731E                <1> 	jnc	short sysexec_0
  2447                              <1> 	;
  2448                              <1> 	; 'file not found !' error
  2449 00004566 C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2449 0000456E 0000                <1>
  2450 00004570 E9AEF5FFFF          <1> 	jmp	error 
  2451                              <1> sysexec_not_exf:
  2452                              <1> 	; 'not executable file !' error
  2453 00004575 C705[476F0000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2453 0000457D 0000                <1>
  2454 0000457F E99FF5FFFF          <1> 	jmp	error 
  2455                              <1> sysexec_0:
  2456 00004584 E85A0C0000          <1> 	call	iget
  2457                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2458                              <1> 	; 03/02/2022
  2459 00004589 F605[F66B0000]10    <1> 	test	byte [i.flgs], 10h
  2460                              <1>         ;test	word [i.flgs], 10h
  2461                              <1> 		; bit $20,i.flgs / is file executable
  2462 00004590 74E3                <1> 	jz	short sysexec_not_exf
  2463                              <1> 	;jz	error
  2464                              <1> 		; beq error9
  2465                              <1> 	;;
  2466 00004592 E8D0130000          <1> 	call	iopen
  2467                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2468                              <1> 			     ; / given in r1 (opens file)
  2469                              <1> 	; AX = i-number of the file
  2470                              <1> 	; 03/02/2022
  2471 00004597 F605[F66B0000]20    <1> 	test	byte [i.flgs], 20h
  2472                              <1> 	;test	word [i.flgs], 20h
  2473                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2474 0000459E 7415                <1> 	jz	short sysexec_1
  2475                              <1> 		; beq 1f
  2476 000045A0 803D[3E6F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2477                              <1> 		; tstb u.uid / test user id
  2478 000045A7 760C                <1> 	jna	short sysexec_1
  2479                              <1> 		; beq 1f / super user
  2480 000045A9 8A0D[F96B0000]      <1> 	mov	cl, [i.uid]
  2481 000045AF 880D[3E6F0000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2482                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2483                              <1> 				 ; / as process user id
  2484                              <1> sysexec_1:
  2485                              <1> 	; 03/02/2022
  2486                              <1> 	; 18/10/2215
  2487                              <1> 	; 10/10/2015
  2488                              <1> 	; 21/07/2015, 24/07/2015
  2489                              <1> 	; 24/06/2015, 25/06/2015
  2490                              <1>         ; Moving arguments to the end of [u.upage]
  2491                              <1> 	; (by regarding page borders in user's memory space)
  2492                              <1> 	;
  2493                              <1> 	; 10/10/2015
  2494                              <1> 	; 21/07/2015
  2495 000045B5 89E5                <1> 	mov	ebp, esp ; (**)
  2496                              <1> 	; 18/10/2015
  2497 000045B7 89EF                <1> 	mov 	edi, ebp
  2498 000045B9 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2499                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2500 000045BE 29CF                <1> 	sub	edi, ecx
  2501 000045C0 89FC                <1> 	mov	esp, edi
  2502 000045C2 31C0                <1> 	xor	eax, eax
  2503 000045C4 A3[206F0000]        <1> 	mov 	[u.nread], eax ; 0
  2504                              <1> 	; 03/02/2022
  2505                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2506                              <1> 	; may leave it with any value after an error))
  2507                              <1> 	;mov	[argc], ax
  2508 000045C9 A2[6E6F0000]        <1> 	mov	[argc], al ; 0
  2509                              <1> 	;
  2510 000045CE 49                  <1> 	dec	ecx ; 256 - 1
  2511 000045CF 890D[1C6F0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2512                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2513                              <1> sysexec_2:
  2514 000045D5 8B35[706F0000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2515 000045DB E861020000          <1> 	call	get_argp
  2516                              <1> 	;mov	ecx, 4 
  2517                              <1> 	; 03/02/2022
  2518 000045E0 31C9                <1> 	xor	ecx, ecx
  2519 000045E2 B104                <1> 	mov	cl, 4
  2520                              <1> sysexec_3:
  2521 000045E4 21C0                <1> 	and	eax, eax
  2522 000045E6 7456                <1> 	jz	short sysexec_6
  2523                              <1> 	; 18/10/2015
  2524 000045E8 010D[706F0000]      <1> 	add	[argv], ecx ; 4
  2525 000045EE 66FF05[6E6F0000]    <1> 	inc	word [argc]
  2526                              <1> 	;
  2527 000045F5 A3[186F0000]        <1> 	mov	[u.base], eax
  2528                              <1>  	; 23/10/2015
  2529 000045FA 66C705[576F0000]00- <1> 	mov	word [u.pcount], 0
  2529 00004602 00                  <1>
  2530                              <1> sysexec_4:
  2531 00004603 E852110000          <1> 	call	cpass ; get a character from user's core memory
  2532 00004608 750B                <1>         jnz	short sysexec_5
  2533                              <1> 		; (max. 255 chars + null)
  2534                              <1> 	; 18/10/2015
  2535 0000460A 28C0                <1> 	sub 	al, al
  2536 0000460C AA                  <1> 	stosb
  2537 0000460D FF05[206F0000]      <1> 	inc	dword [u.nread]
  2538 00004613 EB29                <1> 	jmp	short sysexec_6
  2539                              <1> sysexec_5:
  2540 00004615 AA                  <1> 	stosb
  2541 00004616 20C0                <1> 	and 	al, al
  2542 00004618 75E9                <1> 	jnz	short sysexec_4
  2543                              <1> 	;mov	ecx, 4
  2544                              <1> 	; 03/02/2022
  2545 0000461A 29C9                <1> 	sub	ecx, ecx
  2546 0000461C B104                <1> 	mov	cl, 4
  2547                              <1> 	;cmp	[ncount], ecx ; 4
  2548                              <1> 	; 03/02/2022
  2549 0000461E 66390D[6C6F0000]    <1> 	cmp	[ncount], cx ; 4
  2550 00004625 72AE                <1> 	jb	short sysexec_2
  2551 00004627 8B35[686F0000]      <1> 	mov	esi, [nbase]
  2552 0000462D 010D[686F0000]      <1> 	add	[nbase], ecx ; 4	
  2553 00004633 66290D[6C6F0000]    <1> 	sub	[ncount], cx 
  2554 0000463A 8B06                <1> 	mov	eax, [esi]
  2555 0000463C EBA6                <1> 	jmp	short sysexec_3
  2556                              <1> sysexec_6:
  2557                              <1> 	; 18/10/2015
  2558                              <1> 	; argument list transfer from user's core memory to
  2559                              <1> 	; kernel stack frame is OK here.
  2560                              <1> 	; [u.nread] = ; argument list length
  2561                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2562                              <1> 	;
  2563                              <1> 	; 18/10/2015
  2564                              <1>         ; 21/07/2015, 24/07/2015
  2565                              <1> 	; 25/06/2015, 02/07/2015
  2566                              <1> 	; 23/06/2015, 24/06/2015
  2567                              <1> 	;
  2568 0000463E 8B1D[4F6F0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2569 00004644 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2570 00004646 740A                <1> 	jz	short sysexec_7
  2571 00004648 A1[4B6F0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2572 0000464D E8C6E8FFFF          <1> 	call	deallocate_page_dir
  2573                              <1> sysexec_7:
  2574 00004652 E8F6E7FFFF          <1> 	call	make_page_dir
  2575                              <1> 	;jc	short sysexec_14
  2576                              <1> 	;jc	panic  ; allocation error 
  2577                              <1> 		       ; after a deallocation would be nonsence !?
  2578                              <1> 	; 03/02/2022
  2579 00004657 7243                <1> 	jc	short sysexec_panic
  2580                              <1> 
  2581                              <1> 	; 24/07/2015
  2582                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2583                              <1> 	;     of the user's page directory
  2584                              <1> 	;     (It is needed for interrupts!)
  2585                              <1> 	; 18/10/2015
  2586 00004659 8B15[486B0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2587 0000465F 8B02                <1> 	mov	eax, [edx] ; physical address of
  2588                              <1> 			   ; kernel's first page table (1st 4 MB)
  2589                              <1> 			   ; (PDE 0 of kernel's page directory)
  2590 00004661 8B15[4B6F0000]      <1> 	mov 	edx, [u.pgdir]
  2591 00004667 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2592                              <1> 	;
  2593                              <1> 	; 20/07/2015
  2594 00004669 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2595                              <1> 	; 18/10/2015
  2596 0000466E BE[606F0000]        <1> 	mov	esi, pcore ; physical start address
  2597                              <1> sysexec_8:	
  2598 00004673 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2599 00004678 E8EEE7FFFF          <1> 	call	make_page_table
  2600                              <1> 	;jc	panic
  2601                              <1> 	; 03/02/2022
  2602 0000467D 721D                <1> 	jc	short sysexec_panic
  2603                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2604 0000467F E8F5E7FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2605                              <1> 	;jc	panic
  2606                              <1> 	; 03/02/2022
  2607 00004684 7216                <1> 	jc	short sysexec_panic
  2608                              <1> 	;
  2609 00004686 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2610                              <1> 	; ebx = virtual address (24/07/2015)
  2611                              <1> 	; 03/02/2022
  2612                              <1> 	;call 	add_to_swap_queue
  2613                              <1> 	; 18/10/2015
  2614 00004688 81FE[646F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2615 0000468E 7411                <1> 	je	short sysexec_9 ; yes
  2616 00004690 BE[646F0000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2617                              <1> 	; 20/07/2015
  2618 00004695 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2619                              <1> 	; ebx = virtual end address + segment base address - 4K
  2620 0000469A EBD7                <1>         jmp     short sysexec_8
  2621                              <1> 
  2622                              <1> sysexec_panic:
  2623                              <1> 	; 03/02/2022
  2624 0000469C E930EDFFFF          <1> 	jmp	panic
  2625                              <1> 
  2626                              <1> sysexec_9:
  2627                              <1> 	; 18/10/2015
  2628                              <1> 	; 26/08/2015
  2629                              <1> 	; 25/06/2015
  2630                              <1> 	; move arguments from kernel stack to [ecore]
  2631                              <1> 	; (argument list/line will be copied from kernel stack
  2632                              <1> 	; frame to the last (stack) page of user's core memory)
  2633                              <1> 	; 18/10/2015
  2634 000046A1 8B3D[646F0000]      <1> 	mov	edi, [ecore]
  2635 000046A7 81C700100000        <1> 	add	edi, PAGE_SIZE
  2636                              <1> 	;movzx	eax, word [argc]
  2637                              <1> 	; 03/02/2022
  2638 000046AD 31C0                <1> 	xor	eax, eax
  2639 000046AF A0[6E6F0000]        <1> 	mov	al, [argc]
  2640 000046B4 08C0                <1> 	or	al, al
  2641                              <1> 	;or	eax, eax
  2642 000046B6 7509                <1> 	jnz	short sysexec_10
  2643 000046B8 89FB                <1> 	mov 	ebx, edi
  2644 000046BA 83EB04              <1> 	sub	ebx, 4 
  2645 000046BD 8903                <1> 	mov	[ebx], eax ; 0
  2646 000046BF EB40                <1> 	jmp 	short sysexec_13
  2647                              <1> sysexec_10:
  2648 000046C1 8B0D[206F0000]      <1> 	mov	ecx, [u.nread]
  2649                              <1> 	;mov 	esi, [argv}
  2650 000046C7 89E6                <1> 	mov	esi, esp ; start address of argument list
  2651 000046C9 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2652 000046CB 89C2                <1> 	mov	edx, eax
  2653                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2654 000046CD FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2655 000046CF C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2656                              <1> 	; edx <= 128
  2657 000046D2 89FB                <1> 	mov	ebx, edi
  2658 000046D4 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2659 000046D7 29D3                <1> 	sub 	ebx, edx
  2660 000046D9 89FA                <1> 	mov	edx, edi
  2661 000046DB F3A4                <1> 	rep	movsb
  2662 000046DD 89D6                <1> 	mov 	esi, edx
  2663 000046DF 89DF                <1> 	mov 	edi, ebx
  2664 000046E1 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2665 000046E6 2B15[646F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2666 000046EC AB                  <1> 	stosd	; eax = argument count	
  2667                              <1> sysexec_11:
  2668 000046ED 89F0                <1> 	mov	eax, esi
  2669 000046EF 01D0                <1> 	add	eax, edx
  2670 000046F1 AB                  <1> 	stosd  ; eax = virtual address
  2671 000046F2 FE0D[6E6F0000]      <1> 	dec	byte [argc]
  2672 000046F8 7407                <1> 	jz	short sysexec_13
  2673                              <1> sysexec_12:
  2674 000046FA AC                  <1> 	lodsb
  2675 000046FB 20C0                <1> 	and	al, al
  2676 000046FD 75FB                <1> 	jnz	short sysexec_12
  2677 000046FF EBEC                <1> 	jmp	short sysexec_11
  2678                              <1> 	;
  2679                              <1> 	; 1:
  2680                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2681                              <1> 			     ; / pointers to arguments to be passed
  2682                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2683                              <1> 			      ; / u.quit = 1 take quit
  2684                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2685                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2686                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2687                              <1> 			       ; / system routine
  2688                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2689                              <1> 			       ; / set to take system routine
  2690                              <1> 		; mov $sstack,sp / stack space used during swapping
  2691                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2692                              <1> 		; mov $ecore,r5 / r5 has end of core
  2693                              <1> 		; mov $core,r4 / r4 has start of users core
  2694                              <1> 		; mov r4,u.base / u.base has start of users core
  2695                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2696                              <1> 	; 1:
  2697                              <1> 		; tst (r2)+ / argument char = "nul"
  2698                              <1> 		; bne 1b
  2699                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2700                              <1> 			  ; / end of argument pointer list
  2701                              <1> 	; 1:
  2702                              <1> 	     ; / move arguments to bottom of users core
  2703                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2704                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2705                              <1> 			    ; / ptr list
  2706                              <1> 		; blo 1f / branch to 1f when all arguments
  2707                              <1> 		       ; / are moved
  2708                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2709                              <1> 	; 2:
  2710                              <1> 		; tstb (r3)+
  2711                              <1> 		; bne 2b / scan argument for \0 (nul)
  2712                              <1> 
  2713                              <1> 	; 2:
  2714                              <1> 		; movb -(r3),-(r5) / move argument char 
  2715                              <1> 				 ; / by char starting at "ecore"
  2716                              <1> 		; cmp r3,(r2) / moved all characters in 
  2717                              <1> 			    ; / this argument
  2718                              <1> 		; bhi 2b / branch 2b if not
  2719                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2720                              <1> 			     ; / r5 has pointer to nth arg
  2721                              <1> 		; br 1b / string
  2722                              <1> 	; 1:
  2723                              <1> 		; clrb -(r5)
  2724                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2725                              <1> 			 ; / last word of argument strings
  2726                              <1> 		; mov $core,r2
  2727                              <1> 	
  2728                              <1> 	; 1: / move argument pointers into core following 
  2729                              <1> 	      ; / argument strings
  2730                              <1> 		; cmp r2,r4
  2731                              <1> 		; bhis 1f / branch to 1f when all pointers
  2732                              <1> 			; / are moved
  2733                              <1> 		; mov (r2)+,-(r5)
  2734                              <1> 		; br 1b
  2735                              <1> 	; 1:
  2736                              <1> 		; sub $core,r4 / gives number of arguments *2
  2737                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2738                              <1> 		       ; / the number of args stored
  2739                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2740                              <1> 			     ; / of the argument pointers
  2741                              <1> sysexec_13:
  2742                              <1> 	; 19/10/2015
  2743                              <1> 	; 18/10/2015
  2744                              <1> 	; 29/07/2015
  2745                              <1> 	; 24/07/2015, 25/07/2015
  2746                              <1> 	; 25/06/2015, 20/07/2015
  2747                              <1> 	; 23/06/2015, 24/06/2015
  2748                              <1> 	;
  2749                              <1> 	; moving arguments to [ecore] is OK here..
  2750                              <1> 	; 18/10/2015
  2751 00004701 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2752                              <1> 	; ebx = beginning addres of argument list pointers
  2753                              <1> 	;	in user's stack
  2754                              <1> 	; 19/10/2015
  2755 00004703 2B1D[646F0000]      <1> 	sub 	ebx, [ecore]
  2756 00004709 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2757                              <1> 			; end of core - 4096 (last page)
  2758                              <1> 			; (virtual address)
  2759 0000470F 891D[706F0000]      <1> 	mov	[argv], ebx
  2760 00004715 891D[246F0000]      <1> 	mov	[u.break], ebx ; available user memory
  2761                              <1> 	;
  2762 0000471B 29C0                <1> 	sub	eax, eax
  2763 0000471D C705[1C6F0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2763 00004725 0000                <1>
  2764                              <1> 		; mov $14,u.count
  2765 00004727 C705[086F0000]-     <1> 	mov	dword [u.fofp], u.off
  2765 0000472D [146F0000]          <1>
  2766                              <1> 		; mov $u.off,u.fofp
  2767 00004731 A3[146F0000]        <1> 	mov	[u.off], eax ; 0
  2768                              <1> 		; clr u.off / set offset in file to be read to zero
  2769                              <1> 	; 25/07/2015
  2770 00004736 A3[186F0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2771                              <1> 	; 25/06/2015 
  2772 0000473B 66A1[DA6E0000]      <1> 	mov	ax, [ii]
  2773                              <1> 	; AX = i-number of the executable file
  2774 00004741 E8710C0000          <1> 	call	readi
  2775                              <1> 		; jsr r0,readi / read in first six words of 
  2776                              <1> 			; / user's file, starting at $core
  2777                              <1> 		; mov sp,r5 / put users stack address in r5
  2778                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2779                              <1> 				; / from r5 (leaves number of words
  2780                              <1> 				; / less 26 available for
  2781                              <1> 			     	; / program in user core
  2782                              <1> 		; mov r5,u.count /
  2783                              <1> 	; 25/06/2015
  2784 00004746 8B0D[246F0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2785 0000474C 890D[1C6F0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2786                              <1> 	;
  2787 00004752 8B0D[206F0000]      <1> 	mov	ecx, [u.nread]
  2788 00004758 890D[246F0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2789 0000475E 80F920              <1> 	cmp	cl, 32
  2790 00004761 7540                <1>         jne     short sysexec_15
  2791                              <1> 	;:
  2792                              <1> 	; 25/06/2015
  2793                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2794                              <1> 	; 18/10/2015
  2795 00004763 8B35[606F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2796                              <1> 		             ; (phys. start addr. of the exec. file)
  2797 00004769 AD                  <1> 	lodsd
  2798 0000476A 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2799 0000476E 7533                <1> 	jne	short sysexec_15
  2800                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2801                              <1> 			      ; / if file is standard a.out format
  2802                              <1> 		; bne 1f / branch, if not standard format
  2803 00004770 AD                  <1> 	lodsd
  2804 00004771 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2805 00004773 AD                  <1> 	lodsd
  2806 00004774 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2807                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2808                              <1> 		              ; / number of bytes in program text	
  2809                              <1> 		; sub $14,r5 / subtract 12
  2810 00004776 89CB                <1> 	mov	ebx, ecx
  2811                              <1> 	;
  2812                              <1> 	; 25/06/2015
  2813                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2814                              <1> 	;	and SINGLIX operating systems (as code template).
  2815                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2816                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2817                              <1> 	;	Overrun is not possible for current version. 	
  2818                              <1> 	;
  2819 00004778 AD                  <1> 	lodsd	
  2820 00004779 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2821 0000477B 3B1D[1C6F0000]      <1> 	cmp	ebx, [u.count]
  2822 00004781 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2823                              <1> 	;
  2824                              <1> 	; 24/07/2015
  2825                              <1> 	; add bss section size to [u.break]
  2826 00004783 0105[246F0000]      <1> 	add 	[u.break], eax
  2827                              <1> 	;
  2828 00004789 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2829                              <1> 	;cmp	ecx, [u.count]
  2830                              <1> 	;jnb	short sysexec_16
  2831                              <1> 		; cmp r5,u.count /
  2832                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2833 0000478C 890D[1C6F0000]      <1> 	mov	[u.count], ecx ; required read count
  2834                              <1> 		; mov r5,u.count
  2835                              <1> 	;
  2836 00004792 EB2A                <1> 	jmp	short sysexec_16
  2837                              <1> 	;
  2838                              <1> sysexec_14:
  2839                              <1> 	; 23/06/2015
  2840                              <1> 	; insufficient (out of) memory
  2841 00004794 C705[476F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2841 0000479C 0000                <1>
  2842 0000479E E980F3FFFF          <1> 	jmp	error
  2843                              <1> 	;
  2844                              <1> sysexec_15:
  2845                              <1> 	; 25/06/2015
  2846 000047A3 0FB715[FA6B0000]    <1>         movzx   edx, word [i.size] ; file size
  2847 000047AA 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2848 000047AC 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2849 000047AE 01D1                <1> 	add	ecx, edx ; [i.size]
  2850 000047B0 3B0D[1C6F0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2851 000047B6 77DC                <1> 	ja	short sysexec_14
  2852 000047B8 8915[1C6F0000]      <1> 	mov	[u.count], edx
  2853                              <1> sysexec_16:
  2854 000047BE 66A1[DA6E0000]      <1> 	mov	ax, [ii] ; i-number
  2855 000047C4 E8EE0B0000          <1> 	call	readi
  2856                              <1> 		; add core+10,u.nread / add size of user data area 
  2857                              <1> 		                    ; / to u.nread
  2858                              <1> 		; br 2f
  2859                              <1> 	; 1:
  2860                              <1> 		; jsr r0,readi / read in rest of file
  2861                              <1> 	; 2:
  2862 000047C9 8B0D[206F0000]      <1> 	mov	ecx, [u.nread]
  2863 000047CF 010D[246F0000]      <1> 	add	[u.break], ecx
  2864                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2865                              <1> 				    ; / user code
  2866                              <1> 		; add $core+14,u.break / plus data area
  2867                              <1> sysexec_17: ; 20/07/2015
  2868                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2869                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2870                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2871                              <1> 	;;mov	ax, [ii] ; i-number
  2872                              <1> 	;call	iclose
  2873                              <1> 	;	; jsr r0,iclose / does nothing
  2874 000047D5 31C0                <1>         xor     eax, eax
  2875 000047D7 FEC0                <1> 	inc	al
  2876 000047D9 66A3[366F0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2877 000047DF 66A3[386F0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2878                              <1> 	; 02/07/2015
  2879 000047E5 833D[4F6F0000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2880 000047EC 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2881                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2882 000047EE 8B15[486B0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2883 000047F4 8915[4F6F0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2884                              <1> sysexec_18:
  2885                              <1> 	; 18/10/2015
  2886                              <1> 	; 05/08/2015
  2887                              <1> 	; 29/07/2015
  2888 000047FA 8B2D[706F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2889                              <1> 			    ; list pointers (argument count)
  2890 00004800 FA                  <1> 	cli
  2891 00004801 8B25[E46A0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2892                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2893                              <1> 			    ; for this process	 
  2894                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2895                              <1> 	;xor	eax, eax ; 0
  2896 00004807 FEC8                <1> 	dec	al ; eax = 0
  2897 00004809 66BA2300            <1> 	mov	dx, UDATA
  2898 0000480D 6652                <1> 	push	dx  ; user's stack segment
  2899 0000480F 55                  <1> 	push	ebp ; user's stack pointer
  2900                              <1> 		    ; (points to number of arguments)
  2901 00004810 FB                  <1> 	sti
  2902 00004811 9C                  <1> 	pushfd	; EFLAGS
  2903                              <1> 		; Set IF for enabling interrupts in user mode	
  2904                              <1> 	;or	dword [esp], 200h 
  2905                              <1> 	;
  2906                              <1> 	;mov	bx, UCODE
  2907                              <1> 	;push	bx ; user's code segment
  2908 00004812 6A1B                <1> 	push	UCODE
  2909                              <1> 	;push	0
  2910 00004814 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2911                              <1> 		; clr -(r5) / popped into ps when rti in 
  2912                              <1> 			  ; / sysrele is executed
  2913                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2914                              <1> 		                ; / in sysrele is executed
  2915                              <1> 		;mov r5,0f / load second copyz argument
  2916                              <1> 		;tst -(r5) / decrement r5
  2917 00004815 8925[F06E0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2918                              <1> 	; 05/08/2015
  2919                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2920                              <1> 	; ('push dx' would cause to general protection fault, 
  2921                              <1> 	; after 'pop ds' etc.)
  2922                              <1> 	;
  2923                              <1> 	;; push dx ; ds (UDATA)
  2924                              <1> 	;; push dx ; es (UDATA)
  2925                              <1> 	;; push dx ; fs (UDATA)
  2926                              <1> 	;; push dx ; gs (UDATA)
  2927                              <1> 	;
  2928                              <1> 	; This is a trick to prevent general protection fault
  2929                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  2930 0000481B 8EC2                <1> 	mov 	es, dx ; UDATA
  2931 0000481D 06                  <1> 	push 	es ; ds (UDATA)
  2932 0000481E 06                  <1> 	push 	es ; es (UDATA)
  2933 0000481F 06                  <1> 	push 	es ; fs (UDATA)
  2934 00004820 06                  <1> 	push	es ; gs (UDATA)
  2935 00004821 66BA1000            <1> 	mov	dx, KDATA
  2936 00004825 8EC2                <1> 	mov	es, dx
  2937                              <1> 	;
  2938                              <1> 	;; pushad simulation
  2939 00004827 89E5                <1> 	mov	ebp, esp ; esp before pushad
  2940 00004829 50                  <1> 	push	eax ; eax (0)
  2941 0000482A 50                  <1> 	push	eax ; ecx (0)
  2942 0000482B 50                  <1> 	push	eax ; edx (0)
  2943 0000482C 50                  <1> 	push	eax ; ebx (0)
  2944 0000482D 55                  <1> 	push	ebp ; esp before pushad
  2945 0000482E 50                  <1> 	push	eax ; ebp (0)
  2946 0000482F 50                  <1> 	push	eax ; esi (0)		
  2947 00004830 50                  <1> 	push	eax ; edi (0)	
  2948                              <1> 	;
  2949 00004831 A3[F86E0000]        <1> 	mov	[u.r0], eax ; eax = 0
  2950 00004836 8925[F46E0000]      <1> 	mov	[u.usp], esp
  2951                              <1> 		; mov r5,u.r0 /
  2952                              <1> 		; sub $16.,r5 / skip 8 words
  2953                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  2954                              <1> 		;             / effectively zeroes all regs
  2955                              <1> 			    ; / when sysrele is executed
  2956                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  2957                              <1> 		; clr u.break
  2958                              <1> 		; mov r5,sp / point sp to user's stack
  2959                              <1> 	;
  2960 0000483C E904F3FFFF          <1> 	jmp	sysret0
  2961                              <1> 	;jmp	sysret
  2962                              <1> 		; br sysret3 / return to core image at $core
  2963                              <1> 
  2964                              <1> get_argp:
  2965                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2966                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2967                              <1> 	; 18/10/2015 (nbase, ncount)
  2968                              <1> 	; 21/07/2015
  2969                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  2970                              <1> 	; Get (virtual) address of argument from user's core memory
  2971                              <1> 	;
  2972                              <1> 	; INPUT:
  2973                              <1> 	;	esi = virtual address of argument pointer
  2974                              <1> 	; OUTPUT:
  2975                              <1> 	;	eax = virtual address of argument
  2976                              <1> 	;
  2977                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  2978                              <1> 	;
  2979 00004841 833D[4F6F0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  2980                              <1> 				    ; (the caller is kernel)
  2981                              <1>         ;jna	short get_argpk
  2982                              <1> 	; 03/02/2022
  2983 00004848 7719                <1> 	ja	short get_argp5
  2984                              <1> get_argpk:
  2985                              <1> 	; Argument is in kernel's memory space
  2986 0000484A 66C705[6C6F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  2986 00004852 10                  <1>
  2987 00004853 8935[686F0000]      <1> 	mov	[nbase], esi
  2988 00004859 8305[686F0000]04    <1> 	add	dword [nbase], 4
  2989 00004860 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  2990 00004862 C3                  <1> 	retn
  2991                              <1> get_argp5:
  2992 00004863 89F3                <1>      	mov	ebx, esi
  2993 00004865 E86AE9FFFF          <1> 	call	get_physical_addr ; get physical address
  2994 0000486A 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  2995 0000486C A3[686F0000]        <1> 	mov 	[nbase], eax ; physical address	
  2996 00004871 66890D[6C6F0000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  2997 00004878 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  2998                              <1> 	;cmp	cx, ax ; 4
  2999                              <1> 	; 03/02/2022
  3000 0000487D 39C1                <1> 	cmp	ecx, eax
  3001 0000487F 734C                <1> 	jnb	short get_argp2
  3002 00004881 89F3                <1> 	mov	ebx, esi
  3003 00004883 01CB                <1> 	add	ebx, ecx
  3004 00004885 E84AE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3005 0000488A 7237                <1> 	jc	short get_argp_err
  3006                              <1> 	;push	esi
  3007 0000488C 89C6                <1> 	mov	esi, eax
  3008 0000488E 66870D[6C6F0000]    <1> 	xchg	cx, [ncount]
  3009 00004895 8735[686F0000]      <1> 	xchg	esi, [nbase]
  3010 0000489B B504                <1> 	mov	ch, 4
  3011 0000489D 28CD                <1> 	sub	ch, cl
  3012                              <1> get_argp0:
  3013 0000489F AC                  <1> 	lodsb
  3014                              <1> 	;push	ax
  3015                              <1> 	; 03/02/2022
  3016 000048A0 50                  <1> 	push	eax
  3017 000048A1 FEC9                <1> 	dec	cl
  3018 000048A3 75FA                <1>         jnz     short get_argp0
  3019 000048A5 8B35[686F0000]      <1> 	mov	esi, [nbase]
  3020                              <1> 	; 21/07/2015
  3021 000048AB 0FB6C5              <1> 	movzx	eax, ch
  3022 000048AE 0105[686F0000]      <1> 	add	[nbase], eax
  3023 000048B4 662905[6C6F0000]    <1> 	sub	[ncount], ax
  3024                              <1> get_argp1:
  3025 000048BB AC                  <1> 	lodsb
  3026 000048BC FECD                <1> 	dec	ch
  3027 000048BE 7423                <1>         jz      short get_argp3
  3028                              <1>         ;push	ax
  3029                              <1> 	; 03/02/2022
  3030 000048C0 50                  <1> 	push	eax
  3031 000048C1 EBF8                <1> 	jmp     short get_argp1
  3032                              <1> get_argp_err:
  3033 000048C3 A3[476F0000]        <1> 	mov	[u.error], eax
  3034 000048C8 E956F2FFFF          <1> 	jmp	error
  3035                              <1> get_argp2:
  3036                              <1> 	; 21/07/2015
  3037                              <1> 	;mov	eax, 4
  3038 000048CD 8B15[686F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3039 000048D3 0105[686F0000]      <1> 	add	[nbase], eax
  3040 000048D9 662905[6C6F0000]    <1> 	sub	[ncount], ax
  3041                              <1> 	;
  3042 000048E0 8B02                <1> 	mov	eax, [edx]
  3043 000048E2 C3                  <1> 	retn
  3044                              <1> get_argp3:
  3045 000048E3 B103                <1> 	mov	cl, 3
  3046                              <1> get_argp4:
  3047 000048E5 C1E008              <1> 	shl	eax, 8
  3048                              <1> 	;pop	dx
  3049                              <1> 	; 03/02/2022
  3050 000048E8 5A                  <1> 	pop	edx
  3051 000048E9 88D0                <1> 	mov 	al, dl
  3052 000048EB E2F8                <1>         loop    get_argp4
  3053                              <1> 	;pop	esi
  3054 000048ED C3                  <1> 	retn	
  3055                              <1> 
  3056                              <1> sysfstat:
  3057                              <1> 	; 03/02/2022
  3058                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3059                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3060                              <1> 	;
  3061                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3062                              <1> 	; on open files instead of files given by name. It puts the
  3063                              <1> 	; buffer address on the stack, gets the i-number and
  3064                              <1> 	; checks to see if the file is open for reading or writing.
  3065                              <1> 	; If the file is open for writing (i-number is negative)
  3066                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3067                              <1> 	; is made.	
  3068                              <1> 	;
  3069                              <1> 	; Calling sequence:
  3070                              <1> 	;	sysfstat; buf
  3071                              <1> 	; Arguments:
  3072                              <1> 	;	buf - buffer address
  3073                              <1> 	;
  3074                              <1> 	; Inputs: *u.r0 - file descriptor
  3075                              <1> 	; Outputs: buffer is loaded with file information
  3076                              <1> 	; ...............................................................
  3077                              <1> 	;				
  3078                              <1> 	; Retro UNIX 8086 v1 modification:
  3079                              <1> 	;       'sysfstat' system call has two arguments; so,
  3080                              <1> 	;	* 1st argument, file descriptor is in BX register
  3081                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3082                              <1> 
  3083                              <1> 	; / set status of open file
  3084                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3085 000048EE 51                  <1> 	push	ecx
  3086                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3087                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3088                              <1> 		; jsr r0,getf / get the files i-number
  3089                              <1> 	; BX = file descriptor (file number)
  3090 000048EF E8F2000000          <1> 	call	getf1
  3091                              <1> 	; 03/02/2022
  3092 000048F4 21C0                <1> 	and	eax, eax
  3093                              <1> 	;and	ax, ax ; i-number of the file
  3094                              <1> 		; tst	r1 / is it 0?
  3095                              <1> 	;jz	error
  3096                              <1> 		; beq error3 / yes, error
  3097 000048F6 750F                <1> 	jnz	short sysfstat1
  3098 000048F8 C705[476F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3098 00004900 0000                <1>
  3099 00004902 E91CF2FFFF          <1> 	jmp	error
  3100                              <1> sysfstat1:
  3101 00004907 80FC80              <1> 	cmp	ah, 80h
  3102 0000490A 7222                <1>         jb      short sysstat1
  3103                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3104 0000490C 66F7D8              <1> 	neg	ax
  3105                              <1> 		; neg r1 / make it positive, then branch
  3106 0000490F EB1D                <1> 	jmp	short sysstat1
  3107                              <1> 		; br 1f / to 1f
  3108                              <1> sysstat:
  3109                              <1> 	; 03/02/2022
  3110                              <1> 	; 18/10/2015
  3111                              <1> 	; 07/10/2015
  3112                              <1> 	; 02/09/2015
  3113                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3114                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3115                              <1> 	;
  3116                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3117                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3118                              <1> 	; long and information about the file placed in it.	
  3119                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3120                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3121                              <1> 	; is then loaded and the results are given in the UNIX
  3122                              <1> 	; Programmers Manual sysstat (II).	
  3123                              <1> 	;
  3124                              <1> 	; Calling sequence:
  3125                              <1> 	;	sysstat; name; buf
  3126                              <1> 	; Arguments:
  3127                              <1> 	;	name - points to the name of the file
  3128                              <1> 	;	buf - address of a 34 bytes buffer
  3129                              <1> 	; Inputs: -
  3130                              <1> 	; Outputs: buffer is loaded with file information
  3131                              <1> 	; ...............................................................
  3132                              <1> 	;				
  3133                              <1> 	; Retro UNIX 8086 v1 modification: 
  3134                              <1> 	;       'sysstat' system call has two arguments; so,
  3135                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3136                              <1> 	;	to get sysstat system call arguments from the user;
  3137                              <1> 	;	* 1st argument, name is pointed to by BX register
  3138                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3139                              <1> 	;
  3140                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3141                              <1> 	;	      arguments which were in these registers;
  3142                              <1> 	;	      but, it returns by putting the 1st argument
  3143                              <1> 	;	      in 'u.namep' and the 2nd argument
  3144                              <1> 	;	      on top of stack. (1st argument is offset of the
  3145                              <1> 	;	      file/path name in the user's program segment.)		 	
  3146                              <1> 	
  3147                              <1> 	; / ; name of file; buffer - get files status
  3148                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3149 00004911 891D[106F0000]      <1> 	mov	[u.namep], ebx
  3150 00004917 51                  <1> 	push	ecx
  3151 00004918 E8FC000000          <1> 	call	namei
  3152                              <1> 		; jsr r0,namei / get the i-number for the file
  3153                              <1> 	;jc	error
  3154                              <1> 		; br error3 / no such file, error
  3155 0000491D 730F                <1> 	jnc	short sysstat1
  3156                              <1> 	; pop 	ecx
  3157                              <1> sysstat_err0:
  3158                              <1> 	; 'file not found !' error
  3159 0000491F C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3159 00004927 0000                <1>
  3160 00004929 E9F5F1FFFF          <1> 	jmp	error
  3161                              <1> 
  3162                              <1> ;statx: db 0
  3163                              <1> 
  3164                              <1> sysstat1: ; 1:
  3165 0000492E E8B0080000          <1> 	call	iget
  3166                              <1> 		; jsr r0,iget / get the i-node into core
  3167                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3168                              <1> 	; 02/09/2015
  3169 00004933 8F05[186F0000]      <1> 	pop	dword [u.base]
  3170                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3171 00004939 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3172 0000493E 730A                <1> 	jnc 	short sysstat2
  3173                              <1> sysstat_err1:
  3174 00004940 A3[476F0000]        <1> 	mov	dword [u.error], eax ; error code
  3175 00004945 E9D9F1FFFF          <1> 	jmp	error
  3176                              <1> sysstat2:
  3177 0000494A A0[DA6E0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3178 0000494F AA                  <1> 	stosb
  3179 00004950 FF05[186F0000]      <1> 	inc 	dword [u.base]
  3180                              <1> 	;dec 	cx
  3181                              <1> 	; 03/02/2022
  3182 00004956 49                  <1> 	dec	ecx
  3183 00004957 7505                <1> 	jnz	short sysstat3
  3184 00004959 E835000000          <1> 	call	sysstat_gpa
  3185                              <1> 	;jc	short sysstat_err1
  3186                              <1> sysstat3:
  3187 0000495E A0[DB6E0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3188 00004963 AA                  <1> 	stosb
  3189                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3190 00004964 FF05[186F0000]      <1> 	inc 	dword [u.base]
  3191                              <1> 	;;dec 	word [u.pcount]
  3192                              <1> 	;dec	cx
  3193                              <1> 	; 03/02/2022
  3194 0000496A 49                  <1> 	dec	ecx
  3195 0000496B 7505                <1> 	jnz	short sysstat4
  3196 0000496D E821000000          <1> 	call	sysstat_gpa
  3197                              <1> 	;jc	short sysstat_err1	
  3198                              <1> sysstat4:
  3199 00004972 BE[F66B0000]        <1> 	mov	esi, inode
  3200                              <1> 		; mov $inode,r2 / r2 points to i-node
  3201                              <1> sysstat5: ; 1:
  3202 00004977 A4                  <1> 	movsb
  3203                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3204 00004978 FF05[186F0000]      <1> 	inc 	dword [u.base]
  3205                              <1> 	;;dec 	word [u.pcount]
  3206                              <1> 	;dec	cx
  3207                              <1> 	; 03/02/2022
  3208 0000497E 49                  <1> 	dec	ecx
  3209 0000497F 7505                <1> 	jnz	short sysstat6
  3210 00004981 E80D000000          <1> 	call	sysstat_gpa
  3211                              <1> 	;jc	short sysstat_err1
  3212                              <1> sysstat6:		
  3213 00004986 81FE[166C0000]      <1> 	cmp	esi, inode + 32
  3214                              <1> 		; cmp r2,$inode+32 / done?
  3215 0000498C 75E9                <1> 	jne	short sysstat5
  3216                              <1> 		; bne 1b / no, go back
  3217 0000498E E9B0F1FFFF          <1> 	jmp	sysret
  3218                              <1> 		; br sysret3 / return through sysret
  3219                              <1> 	;
  3220                              <1> sysstat_gpa: ; get physical address of file status buffer
  3221                              <1> 	; 02/09/2015
  3222 00004993 8B1D[186F0000]      <1> 	mov 	ebx, [u.base]
  3223                              <1> 	; 07/10/2015
  3224 00004999 E836E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3225                              <1> 	;jc	short sysstat_gpa1
  3226 0000499E 72A0                <1> 	jc	short sysstat_err1
  3227                              <1> 	; 18/10/2015
  3228 000049A0 89C7                <1> 	mov	edi, eax ; physical address
  3229                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3230                              <1> ;sysstat_gpa1:
  3231 000049A2 C3                  <1> 	retn
  3232                              <1> 
  3233                              <1> fclose:
  3234                              <1> 	; 03/02/2022
  3235                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3236                              <1> 	;            (32 bit offset pointer modification)
  3237                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3238                              <1> 	;
  3239                              <1> 	; Given the file descriptor (index to the u.fp list)
  3240                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3241                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3242                              <1> 	; u.fp list is cleared. If all the processes that opened
  3243                              <1> 	; that file close it, then fsp etry is freed and the file
  3244                              <1> 	; is closed. If not a return is taken. 
  3245                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3246                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3247                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3248                              <1> 	; a check is made to see if the file is special.	
  3249                              <1> 	;
  3250                              <1> 	; INPUTS ->
  3251                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3252                              <1> 	;    u.fp - list of entries in the fsp table
  3253                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3254                              <1> 	; OUTPUTS ->
  3255                              <1> 	;    r1 - contains the same file descriptor
  3256                              <1> 	;    r2 - contains i-number
  3257                              <1> 	;
  3258                              <1> 	; ((AX = R1))
  3259                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3260                              <1> 	;
  3261                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3262                              <1> 	;              if i-number of the file is 0. (error)  	
  3263                              <1> 
  3264                              <1> 	;movzx	edx, ax ; **
  3265                              <1> 	; 03/02/2022
  3266                              <1> 	;movzx	edx, al
  3267 000049A3 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3268 000049A5 50                  <1> 	push	eax ; ***
  3269                              <1> 	;push	ax ; ***
  3270                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3271                              <1> 			     ; / the index to u.fp list)
  3272 000049A6 E839000000          <1> 	call	getf
  3273                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3274                              <1> 			    ; / cdev has device =, u.fofp 
  3275                              <1> 			    ; / points to 3rd word of fsp entry
  3276 000049AB 6683F801            <1> 	cmp	ax, 1 ; r1
  3277                              <1> 		; tst r1 / is i-number 0?
  3278 000049AF 7231                <1> 	jb	short fclose_2
  3279                              <1> 		; beq 1f / yes, i-node not active so return
  3280                              <1> 		; tst (r0)+ / no, jump over error return
  3281 000049B1 89D3                <1> 	mov	ebx, edx ; **
  3282                              <1> 	; 03/02/2022
  3283 000049B3 89C2                <1> 	mov	edx, eax ; *
  3284                              <1> 	;mov 	dx, ax ; *
  3285                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3286                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3287                              <1> 			    ; / which is index to u.fp ; **
  3288 000049B5 C683[FE6E0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3289                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3290 000049BC 8B1D[086F0000]      <1> 	mov	ebx, [u.fofp]
  3291                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3292                              <1> fclose_0:
  3293 000049C2 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3294                              <1> 		; decb 2(r1) / decrement the number of processes 
  3295                              <1> 			   ; / that have opened the file
  3296 000049C5 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3297                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3298                              <1> 	;
  3299                              <1> 	; 03/02/2022
  3300 000049C7 52                  <1> 	push	edx ; *
  3301                              <1> 	;push	dx ; *
  3302                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3303                              <1> 	;xor	ax, ax ; 0
  3304                              <1> 	; 03/02/2022
  3305 000049C8 31C0                <1> 	xor	eax, eax
  3306 000049CA 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3307                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3308 000049CE 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3309                              <1> 		; tstb	3(r1) / has this file been deleted
  3310 000049D1 20C0                <1> 	and	al, al
  3311 000049D3 7407                <1> 	jz	short fclose_1
  3312                              <1> 		; beq 2f / no, branch
  3313                              <1> 	; 03/02/2022
  3314 000049D5 89D0                <1> 	mov	eax, edx
  3315                              <1> 	;mov	ax, dx ; *
  3316                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3317                              <1> 	; AX = inode number
  3318 000049D7 E85E040000          <1> 	call	anyi
  3319                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3320                              <1> 			    ; / check if file appears in fsp again
  3321                              <1> fclose_1: ; 2:
  3322                              <1> 	; 03/02/2022
  3323 000049DC 58                  <1> 	pop	eax ; * 
  3324                              <1> 	;pop	ax ; *
  3325                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3326 000049DD E8C8100000          <1> 	call	iclose ; close if it is special file 
  3327                              <1> 		; jsr r0,iclose / check to see if its a special file
  3328                              <1> fclose_2: ; 1:
  3329                              <1> 	; 03/02/2022
  3330 000049E2 58                  <1> 	pop	eax ; ***
  3331                              <1> 	;pop	ax ; ***
  3332                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3333 000049E3 C3                  <1> 	retn
  3334                              <1> 		; rts r0
  3335                              <1> 
  3336                              <1> getf:	; / get the device number and the i-number of an open file
  3337                              <1> 	; 03/02/2022
  3338                              <1> 	; 13/05/2015
  3339                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3340                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3341                              <1> 	;
  3342 000049E4 89C3                <1> 	mov	ebx, eax
  3343                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3344                              <1> 	; 03/02/2022
  3345 000049E6 29C0                <1> 	sub	eax, eax
  3346                              <1> 	;
  3347 000049E8 83FB0A              <1> 	cmp	ebx, 10
  3348                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3349 000049EB 732B                <1>         jnb	short getf2 ; 13/05/2015
  3350                              <1> 	;jnb	error
  3351                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3352                              <1> 			    ; / index in fsp table
  3353                              <1> 	; 03/02/2022
  3354 000049ED 8A83[FE6E0000]      <1> 	mov	al, [ebx+u.fp]
  3355                              <1> 	;mov	bl, [ebx+u.fp]
  3356                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3357                              <1> 		                  ; / in fsp table
  3358                              <1> 	; 03/02/2022
  3359 000049F3 08C0                <1> 	or	al, al
  3360 000049F5 7421                <1> 	jz	short getf2
  3361                              <1> 	;or	bl, bl
  3362                              <1> 	;jnz	short getf3
  3363                              <1> 	;;jz	short getf4
  3364                              <1> 		; beq 1f / if its zero return
  3365                              <1> ;getf2:
  3366                              <1> ;	; 'File not open !' error (ax=0)
  3367                              <1> ;	sub	eax, eax
  3368                              <1> ;	retn
  3369                              <1> 
  3370                              <1> getf3:	
  3371                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3372                              <1> 	;
  3373                              <1> 	; 'fsp' table (10 bytes/entry)
  3374                              <1> 	; bit 15				   bit 0
  3375                              <1> 	; ---|-------------------------------------------
  3376                              <1> 	; r/w|		i-number of open file
  3377                              <1> 	; ---|-------------------------------------------
  3378                              <1> 	;		   device number
  3379                              <1> 	; -----------------------------------------------
  3380                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3381                              <1> 	; -----------------------------------------------
  3382                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3383                              <1> 	; ----------------------|------------------------
  3384                              <1> 	;  flag that says file 	| number of processes
  3385                              <1> 	;   has been deleted	| that have file open 
  3386                              <1> 	; ----------------------|------------------------
  3387                              <1> 	;
  3388                              <1> 	;mov	eax, 10
  3389                              <1> 	; 03/02/2022
  3390 000049F7 B30A                <1> 	mov	bl, 10
  3391 000049F9 F6E3                <1> 	mul	bl
  3392 000049FB BB[C06C0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3393 00004A00 01C3                <1> 	add	ebx, eax
  3394                              <1> 		; asl r1
  3395                              <1> 		; asl r1 / multiply by 8 to get index into 
  3396                              <1> 		       ; / fsp table entry
  3397                              <1> 		; asl r1
  3398                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3399                              <1> 			      ; / in the fsp entry
  3400 00004A02 891D[086F0000]      <1> 	mov	[u.fofp], ebx
  3401                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3402                              <1> 			      ; / in fsp entry in u.fofp
  3403 00004A08 4B                  <1> 	dec	ebx
  3404 00004A09 4B                  <1> 	dec	ebx
  3405                              <1> 	;mov	al, [ebx]
  3406 00004A0A 668B03              <1> 	mov	ax, [ebx]
  3407                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3408 00004A0D 66A3[DE6E0000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3409                              <1> 			     ;;dev number is in 1 byte
  3410                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3411 00004A13 4B                  <1> 	dec	ebx
  3412 00004A14 4B                  <1> 	dec	ebx
  3413 00004A15 668B03              <1> 	mov	ax, [ebx]
  3414                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3415                              <1> getf2:	; 03/02/2022
  3416                              <1> getf4:	; 1:
  3417 00004A18 C3                  <1> 	retn
  3418                              <1> 		; rts r0
  3419                              <1> 
  3420                              <1> namei:
  3421                              <1> 	; 03/02/2022
  3422                              <1> 	; 18/10/2015 (nbase, ncount)
  3423                              <1> 	; 12/10/2015
  3424                              <1> 	; 21/08/2015
  3425                              <1> 	; 18/07/2015
  3426                              <1> 	; 02/07/2015
  3427                              <1> 	; 17/06/2015
  3428                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3429                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3430                              <1> 	;
  3431                              <1> 	; 'namei' takes a file path name and returns i-number of
  3432                              <1> 	; the file in the current directory or the root directory
  3433                              <1> 	; (if the first character of the pathname is '/').	
  3434                              <1> 	;
  3435                              <1> 	; INPUTS ->
  3436                              <1> 	;    u.namep - points to a file path name
  3437                              <1> 	;    u.cdir - i-number of users directory
  3438                              <1> 	;    u.cdev - device number on which user directory resides	
  3439                              <1> 	; OUTPUTS ->
  3440                              <1> 	;    r1 - i-number of file
  3441                              <1> 	;    cdev
  3442                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3443                              <1> 	;               occurs in the search for file path name.
  3444                              <1> 	;	        If no match u.dirb points to the end of 
  3445                              <1> 	;               the directory and r1 = i-number of the current
  3446                              <1> 	;	        directory.	
  3447                              <1> 	; ((AX = R1))
  3448                              <1> 	;
  3449                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3450                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3451                              <1> 	;
  3452                              <1> 
  3453 00004A19 66A1[FC6E0000]      <1> 	mov	ax, [u.cdir]
  3454                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3455                              <1> 			      ; / in r1
  3456 00004A1F 668B15[3C6F0000]    <1> 	mov	dx, [u.cdrv]
  3457 00004A26 668915[DE6E0000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3458                              <1> 				    ; device/drive number is in 1 byte, 
  3459                              <1> 				    ; not in 1 word!
  3460                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3461                              <1> 				; / into cdev
  3462                              <1> 	; 12/10/2015
  3463                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3464                              <1>       	 ; convert virtual (pathname) addr to physical address
  3465 00004A2D E823010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3466                              <1> 		; esi = physical address of [u.namep]
  3467                              <1> 		; ecx = byte count in the page
  3468 00004A32 803E2F              <1> 	cmp	byte [esi], '/'
  3469                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3470 00004A35 751D                <1> 	jne	short namei_1
  3471                              <1> 		; bne 1f
  3472 00004A37 FF05[106F0000]      <1> 	inc	dword [u.namep]
  3473                              <1> 		; inc u.namep / go to next char
  3474                              <1> 	; 03/02/2022
  3475 00004A3D 49                  <1> 	dec	ecx
  3476                              <1> 	;dec	cx ; remain byte count in the page
  3477 00004A3E 7506                <1> 	jnz	short namei_0
  3478                              <1> 	; 12/10/2015
  3479 00004A40 E810010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3480                              <1> 		; esi = physical address (page start + offset)
  3481                              <1> 		; ecx = byte count in the page
  3482 00004A45 4E                  <1> 	dec	esi
  3483                              <1> namei_0:
  3484 00004A46 46                  <1> 	inc 	esi  ; go to next char
  3485 00004A47 66A1[E86E0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3486                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3487 00004A4D C605[DE6E0000]00    <1> 	mov	byte [cdev], 0
  3488                              <1> 		; clr cdev / clear device number
  3489                              <1> namei_1: ; 1:
  3490 00004A54 F606FF              <1> 	test	byte [esi], 0FFh
  3491                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3492 00004A57 74BF                <1> 	jz	short getf4
  3493                              <1> 	;jz	nig
  3494                              <1> 		; tstb *u.namep / is the character in file name a nul
  3495                              <1> 		; beq nig / yes, end of file name reached; 
  3496                              <1> 			; / branch to "nig"
  3497                              <1> namei_2: ; 1:
  3498                              <1> 	; 18/10/2015
  3499 00004A59 8935[686F0000]      <1> 	mov 	[nbase], esi
  3500 00004A5F 66890D[6C6F0000]    <1> 	mov 	[ncount], cx
  3501                              <1> 	;
  3502                              <1> 	;mov	dx, 2
  3503 00004A66 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3504 00004A68 E84A080000          <1> 	call	access
  3505                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3506                              <1> 	; 'access' will not return here if user has not "r" permission !
  3507                              <1> 	; 03/02/2022
  3508 00004A6D F605[F76B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3509                              <1> 	;test 	word [i.flgs], 4000h
  3510                              <1> 		; bit $40000,i.flgs / directory i-node?
  3511 00004A74 746A                <1>         jz      short namei_err
  3512                              <1> 		; beq error3 / no, got an error
  3513                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3514 00004A76 31C0                <1> 	xor	eax, eax
  3515 00004A78 A3[146F0000]        <1> 	mov	[u.off], eax ; 0
  3516 00004A7D 66A1[FA6B0000]      <1> 	mov	ax, [i.size]
  3517 00004A83 A3[0C6F0000]        <1> 	mov	[u.dirp], eax
  3518                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3519                              <1> 		; clr u.off / u.off is file offset used by user
  3520 00004A88 C705[086F0000]-     <1> 	mov	dword [u.fofp], u.off
  3520 00004A8E [146F0000]          <1>
  3521                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3522                              <1> 				  ; / the offset portion of fsp entry
  3523                              <1> namei_3: ; 2:
  3524 00004A92 C705[186F0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3524 00004A98 [2A6F0000]          <1>
  3525                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3526                              <1> 				    ; / copied from a directory
  3527 00004A9C C705[1C6F0000]0A00- <1> 	mov 	dword [u.count], 10 	
  3527 00004AA4 0000                <1>
  3528                              <1>  		; mov $10.,u.count / u.count is byte count 
  3529                              <1> 				 ; / for reads and writes
  3530 00004AA6 66A1[DA6E0000]      <1> 	mov 	ax, [ii]
  3531                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3532 00004AAC FE05[596F0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3533 00004AB2 E800090000          <1>     	call	readi
  3534                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3535                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3536 00004AB7 8B0D[206F0000]      <1> 	mov 	ecx, [u.nread]
  3537 00004ABD 09C9                <1> 	or 	ecx, ecx
  3538                              <1> 		; tst u.nread
  3539 00004ABF 741B                <1> 	jz	short nib
  3540                              <1> 		; ble nib / gives error return
  3541                              <1> 	;
  3542 00004AC1 668B1D[2A6F0000]    <1> 	mov 	bx, [u.dirbuf]
  3543 00004AC8 6621DB              <1> 	and 	bx, bx       
  3544                              <1> 		; tst u.dirbuf /
  3545 00004ACB 7522                <1> 	jnz	short namei_4
  3546                              <1> 		; bne 3f / branch when active directory entry 
  3547                              <1> 		       ; / (i-node word in entry non zero)
  3548 00004ACD A1[146F0000]        <1> 	mov	eax, [u.off]
  3549 00004AD2 83E80A              <1> 	sub	eax, 10
  3550 00004AD5 A3[0C6F0000]        <1> 	mov	[u.dirp], eax
  3551                              <1> 		; mov u.off,u.dirp
  3552                              <1> 		; sub $10.,u.dirp
  3553 00004ADA EBB6                <1> 	jmp	short namei_3
  3554                              <1> 		; br 2b
  3555                              <1> 
  3556                              <1> 	; 18/07/2013
  3557                              <1> nib: 
  3558 00004ADC 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3559 00004ADE F9                  <1> 	stc
  3560                              <1> nig:
  3561 00004ADF C3                  <1> 	retn
  3562                              <1> 
  3563                              <1> namei_err:
  3564                              <1> 	; 16/06/2015
  3565 00004AE0 C705[476F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3565 00004AE8 0000                <1>
  3566 00004AEA E934F0FFFF          <1> 	jmp	error
  3567                              <1> 
  3568                              <1> namei_4: ; 3:
  3569                              <1> 	; 18/10/2015
  3570                              <1> 	; 12/10/2015
  3571                              <1> 	; 21/08/2015
  3572                              <1> 	; 18/07/2015
  3573 00004AEF 8B2D[106F0000]      <1> 	mov	ebp, [u.namep]
  3574                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3575 00004AF5 BF[2C6F0000]        <1> 	mov 	edi, u.dirbuf + 2
  3576                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3577                              <1> 	; 18/10/2015
  3578 00004AFA 8B35[686F0000]      <1> 	mov	esi, [nbase]	
  3579 00004B00 668B0D[6C6F0000]    <1> 	mov	cx, [ncount]
  3580                              <1> 	;
  3581 00004B07 6621C9              <1> 	and	cx, cx
  3582 00004B0A 7505                <1> 	jnz	short namei_5	
  3583                              <1> 	;
  3584 00004B0C E84A000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3585                              <1> 		; esi = physical address (page start + offset)
  3586                              <1> 		; ecx = byte count in the page
  3587                              <1> namei_5: ; 3:
  3588 00004B11 45                  <1> 	inc	ebp ; 18/07/2015
  3589 00004B12 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3590                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3591 00004B13 08C0                <1> 	or 	al, al
  3592 00004B15 741C                <1> 	jz 	short namei_7
  3593                              <1> 		; beq 3f / if char is nul, then the last char in string
  3594                              <1> 			; / has been moved
  3595 00004B17 3C2F                <1> 	cmp	al, '/'
  3596                              <1> 		; cmp r4,$'/ / is char a </>
  3597 00004B19 7418                <1> 	je 	short namei_7
  3598                              <1> 		; beq 3f
  3599                              <1> 	; 03/02/2022
  3600 00004B1B 49                  <1> 	dec	ecx	
  3601                              <1> 	; 12/10/2015
  3602                              <1> 	;dec	cx ; remain byte count in the page
  3603 00004B1C 7505                <1> 	jnz	short namei_6
  3604 00004B1E E838000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3605                              <1> 		; esi = physical address (page start + offset)
  3606                              <1> 		; ecx = byte count in the page
  3607                              <1> namei_6:
  3608 00004B23 81FF[346F0000]      <1>         cmp     edi, u.dirbuf + 10
  3609                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3610                              <1> 				     ; / all 8 bytes of file name
  3611 00004B29 74E6                <1> 	je	short namei_5
  3612                              <1> 		; beq 3b
  3613 00004B2B AE                  <1> 	scasb	
  3614                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3615                              <1> 			      ; / char read from directory
  3616 00004B2C 74E3                <1> 	je 	short namei_5
  3617                              <1> 		; beq 3b / branch if chars match
  3618                              <1> namei_9:
  3619 00004B2E E95FFFFFFF          <1>         jmp    namei_3 ; 2b
  3620                              <1> 		; br 2b / file names do not match go to next directory entry
  3621                              <1> namei_7: ; 3:
  3622 00004B33 81FF[346F0000]      <1> 	cmp	edi, u.dirbuf + 10
  3623                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3624 00004B39 7406                <1> 	je	short namei_8
  3625                              <1> 		; beq 3f
  3626 00004B3B 8A27                <1> 	mov 	ah, [edi]
  3627                              <1> 	;inc 	edi 
  3628 00004B3D 20E4                <1> 	and 	ah, ah
  3629                              <1> 		; tstb (r3)+ /
  3630                              <1>         ;jnz	namei_3
  3631                              <1> 		; bne 2b
  3632                              <1> 	; 03/02/2020
  3633 00004B3F 75ED                <1> 	jnz	short namei_9
  3634                              <1> namei_8: ; 3
  3635 00004B41 892D[106F0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3636                              <1> 		; mov r2,u.namep / u.namep points to char 
  3637                              <1> 			       ; / following a / or nul
  3638                              <1> 	;mov	bx, [u.dirbuf]
  3639                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3640                              <1> 				; / entry to r1
  3641 00004B47 20C0                <1> 	and 	al, al
  3642                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3643                              <1> 		      ;  / if r4 = </> then go to next directory
  3644                              <1> 	; mov	ax, bx
  3645 00004B49 66A1[2A6F0000]      <1> 	mov 	ax, [u.dirbuf] ; 17/06/2015
  3646                              <1>   	; 03/02/2022
  3647 00004B4F E903FFFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3648                              <1> 	;jnz	namei_2 
  3649                              <1> 		; bne 1b
  3650                              <1> 	; AX = i-number of the file
  3651                              <1> ;;nig:
  3652 00004B54 C3                  <1> 	retn
  3653                              <1> 		; tst (r0)+ / gives non-error return
  3654                              <1> ;;nib:
  3655                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3656                              <1> 		       ; ax = 0 -> file not found 
  3657                              <1> ;;	stc	; 27/05/2013
  3658                              <1> ;;	retn
  3659                              <1> 		; rts r0
  3660                              <1> 
  3661                              <1> trans_addr_nmbp:
  3662                              <1> 	; 03/02/2022
  3663                              <1> 	; 18/10/2015
  3664                              <1> 	; 12/10/2015
  3665 00004B55 8B2D[106F0000]      <1> 	mov 	ebp, [u.namep]
  3666                              <1> trans_addr_nm:
  3667                              <1> 	; 03/02/2022
  3668                              <1> 	; Convert virtual (pathname) address to physical address
  3669                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3670                              <1> 	; 18/10/2015
  3671                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3672                              <1> 	; 02/07/2015
  3673                              <1> 	; 17/06/2015
  3674                              <1> 	; 16/06/2015
  3675                              <1> 	;
  3676                              <1> 	; INPUTS: 
  3677                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3678                              <1> 	;	[u.pgdir] = user's page directory
  3679                              <1> 	; OUTPUT:
  3680                              <1> 	;       esi = physical address of the pathname
  3681                              <1> 	;	ecx = remain byte count in the page
  3682                              <1> 	;
  3683                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3684                              <1> 	;
  3685                              <1> 
  3686                              <1> 	; 03/02/2022
  3687 00004B5B 29C9                <1> 	sub	ecx, ecx
  3688                              <1> 
  3689 00004B5D 833D[4F6F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3690 00004B64 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3691                              <1> 				     ; it is already physical address
  3692 00004B66 50                  <1>    	push	eax	
  3693 00004B67 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3694 00004B69 E866E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3695 00004B6E 7204                <1> 	jc	short tr_addr_nm_err
  3696                              <1> 	; 18/10/2015
  3697                              <1> 	; eax = physical address 
  3698                              <1> 	; cx = remain byte count in page (1-4096) 
  3699                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3700 00004B70 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3701 00004B72 58                  <1> 	pop	eax 
  3702 00004B73 C3                  <1> 	retn
  3703                              <1> 
  3704                              <1> tr_addr_nm_err:
  3705 00004B74 A3[476F0000]        <1> 	mov	[u.error], eax
  3706                              <1> 	;pop 	eax
  3707 00004B79 E9A5EFFFFF          <1> 	jmp	error
  3708                              <1> 
  3709                              <1> trans_addr_nmk:
  3710                              <1> 	; 12/10/2015
  3711                              <1> 	; 02/07/2015
  3712 00004B7E 8B35[106F0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3713                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3714                              <1> 	; 03/02/2022
  3715 00004B84 B510                <1> 	mov	ch, PAGE_SIZE/256
  3716 00004B86 C3                  <1> 	retn
  3717                              <1> 
  3718                              <1> syschdir:
  3719                              <1> 	; 03/02/2022
  3720                              <1> 	; / makes the directory specified in the argument
  3721                              <1> 	; / the current directory
  3722                              <1> 	;
  3723                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3724                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3725                              <1> 	;
  3726                              <1> 	; 'syschdir' makes the directory specified in its argument
  3727                              <1> 	; the current working directory.
  3728                              <1> 	;
  3729                              <1> 	; Calling sequence:
  3730                              <1> 	;	syschdir; name
  3731                              <1> 	; Arguments:
  3732                              <1> 	;	name - address of the path name of a directory
  3733                              <1> 	;	       terminated by nul byte.	
  3734                              <1> 	; Inputs: -
  3735                              <1> 	; Outputs: -
  3736                              <1> 	; ...............................................................
  3737                              <1> 	;				
  3738                              <1> 	; Retro UNIX 8086 v1 modification:
  3739                              <1> 	;	 The user/application program puts address of 
  3740                              <1> 	;	 the path name in BX register as 'syschdir' 
  3741                              <1> 	; 	 system call argument.
  3742                              <1> 
  3743 00004B87 891D[106F0000]      <1> 	mov	[u.namep], ebx
  3744                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3745 00004B8D E887FEFFFF          <1> 	call	namei
  3746                              <1> 		; jsr r0,namei / find its i-number
  3747                              <1> 	;jc	error
  3748                              <1> 		; br error3
  3749 00004B92 730F                <1> 	jnc	short syschdir0
  3750                              <1> 	; 'directory not found !' error
  3751 00004B94 C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3751 00004B9C 0000                <1>
  3752 00004B9E E980EFFFFF          <1> 	jmp	error
  3753                              <1> syschdir0:
  3754                              <1> 	; 03/02/2022
  3755 00004BA3 B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3756 00004BA5 E80D070000          <1> 	call	access
  3757                              <1> 		; jsr r0,access; 2 / get i-node into core
  3758                              <1> 	; 03/02/2022
  3759 00004BAA F605[F76B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3760                              <1> 	;test	word [i.flgs], 4000h
  3761                              <1> 		; bit $40000,i.flgs / is it a directory?
  3762                              <1> 	;jz	error 
  3763                              <1> 		; beq error3 / no error
  3764 00004BB1 750F                <1> 	jnz	short syschdir1
  3765 00004BB3 C705[476F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3765 00004BBB 0000                <1>
  3766 00004BBD E961EFFFFF          <1> 	jmp	error
  3767                              <1> syschdir1:
  3768 00004BC2 66A3[FC6E0000]      <1> 	mov	[u.cdir], ax
  3769                              <1> 		; mov r1,u.cdir / move i-number to users 
  3770                              <1> 			      ; / current directory
  3771 00004BC8 66A1[DE6E0000]      <1> 	mov	ax, [cdev]
  3772 00004BCE 66A3[3C6F0000]      <1> 	mov	[u.cdrv], ax
  3773                              <1> 		; mov cdev,u.cdev / move its device to users 
  3774                              <1> 			        ; / current device
  3775 00004BD4 E96AEFFFFF          <1> 	jmp	sysret
  3776                              <1> 		; br sysret3
  3777                              <1> 	
  3778                              <1> syschmod: ; < change mode of file >
  3779                              <1> 	; 03/02/2022
  3780                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3781                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3782                              <1> 	;
  3783                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3784                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3785                              <1> 	; changed to 'mode'.
  3786                              <1> 	;
  3787                              <1> 	; Calling sequence:
  3788                              <1> 	;	syschmod; name; mode
  3789                              <1> 	; Arguments:
  3790                              <1> 	;	name - address of the file name
  3791                              <1> 	;	       terminated by null byte.
  3792                              <1> 	;	mode - (new) mode/flags < attributes >
  3793                              <1> 	;	
  3794                              <1> 	; Inputs: -
  3795                              <1> 	; Outputs: -
  3796                              <1> 	; ...............................................................
  3797                              <1> 	;				
  3798                              <1> 	; Retro UNIX 8086 v1 modification: 
  3799                              <1> 	;       'syschmod' system call has two arguments; so,
  3800                              <1> 	;	* 1st argument, name is pointed to by BX register
  3801                              <1> 	;	* 2nd argument, mode is in CX register
  3802                              <1> 	;
  3803                              <1> 	; Mode bits (Flags):
  3804                              <1> 	;	bit 0 - write permission for non-owner (1)
  3805                              <1> 	;	bit 1 - read permission for non-owner (2)
  3806                              <1> 	;	bit 2 - write permission for owner (4)
  3807                              <1> 	;	bit 3 - read permission for owner (8)
  3808                              <1> 	;	bit 4 - executable flag (16) 	
  3809                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3810                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3811                              <1> 	;	bit 12 - large file flag (4096)
  3812                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3813                              <1> 	;	bit 14 - directory flag (16384)
  3814                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3815                              <1> 
  3816                              <1> 	; / name; mode
  3817 00004BD9 E812000000          <1> 	call	isown
  3818                              <1> 		;jsr r0,isown / get the i-node and check user status
  3819                              <1> 	; 03/02/2022
  3820 00004BDE F605[F76B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3821                              <1> 	;test	word [i.flgs], 4000h
  3822                              <1> 		; bit $40000,i.flgs / directory?
  3823 00004BE5 7402                <1> 	jz	short syschmod1
  3824                              <1> 		; beq 2f / no
  3825                              <1> 	; AL = (new) mode
  3826 00004BE7 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3827                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3828                              <1> 			   ; / executable modes
  3829                              <1> syschmod1: ; 2:
  3830 00004BE9 A2[F66B0000]        <1> 	mov	[i.flgs], al	
  3831                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3832 00004BEE EB42                <1> 	jmp	short isown1
  3833                              <1> 		; br 1f
  3834                              <1> 
  3835                              <1> isown:
  3836                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3837                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3838                              <1> 	;
  3839                              <1> 	; 'isown' is given a file name (the 1st argument).
  3840                              <1> 	;  It find the i-number of that file via 'namei' 
  3841                              <1> 	;  then gets the i-node into core via 'iget'.
  3842                              <1> 	;  It then tests to see if the user is super user. 
  3843                              <1> 	;  If not, it cheks to see if the user is owner of 
  3844                              <1> 	;  the file. If he is not an error occurs.
  3845                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3846                              <1> 	;  the inode has been modificed and the 2nd argument of
  3847                              <1> 	;  the call is put in r2.
  3848                              <1> 	;
  3849                              <1> 	; INPUTS ->
  3850                              <1> 	;    arguments of syschmod and syschown calls
  3851                              <1> 	; OUTPUTS ->
  3852                              <1> 	;    u.uid - id of user
  3853                              <1> 	;    imod - set to a 1
  3854                              <1> 	;    r2 - contains second argument of the system call				 	
  3855                              <1> 	;
  3856                              <1> 	;   ((AX=R2) output as 2nd argument)
  3857                              <1> 	;
  3858                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  3859                              <1> 	;
  3860                              <1> 		; jsr r0,arg2 / u.namep points to file name
  3861                              <1> 	;; ! 2nd argument on top of stack !
  3862                              <1> 	;; 22/06/2015 - 32 bit modifications
  3863                              <1> 	;; 07/07/2013
  3864 00004BF0 891D[106F0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  3865 00004BF6 51                  <1> 	push 	ecx ;; 2nd argument
  3866                              <1> 	;;
  3867 00004BF7 E81DFEFFFF          <1> 	call	namei
  3868                              <1> 		; jsr r0,namei / get its i-number
  3869                              <1>        ; Retro UNIX 8086 v1 modification !
  3870                              <1>        ; ax = 0 -> file not found 
  3871                              <1> 	;and	ax, ax
  3872                              <1> 	;jz	error
  3873                              <1> 	;jc	error ; 27/05/2013
  3874                              <1> 		; br error3
  3875 00004BFC 730F                <1> 	jnc	short isown0
  3876                              <1> 	; 'file not found !' error
  3877 00004BFE C705[476F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3877 00004C06 0000                <1>
  3878 00004C08 E916EFFFFF          <1> 	jmp	error
  3879                              <1> isown0:
  3880 00004C0D E8D1050000          <1> 	call	iget
  3881                              <1> 		; jsr r0,iget / get i-node into core
  3882 00004C12 A0[3E6F0000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  3883 00004C17 08C0                <1> 	or	al, al
  3884                              <1> 		; tstb u.uid / super user?
  3885 00004C19 7417                <1> 	jz	short isown1
  3886                              <1> 		; beq 1f / yes, branch
  3887 00004C1B 3A05[F96B0000]      <1> 	cmp	al, [i.uid]
  3888                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  3889                              <1> 				 ; / the file
  3890                              <1> 	;jne	error
  3891                              <1> 		; beq 1f / yes
  3892                              <1> 		; jmp error3 / no, error
  3893 00004C21 740F                <1> 	je	short isown1
  3894                              <1> 
  3895 00004C23 C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  3895 00004C2B 0000                <1>
  3896                              <1> 			;  'permission denied !' error
  3897 00004C2D E9F1EEFFFF          <1> 	jmp	error
  3898                              <1> isown1: ; 1:
  3899 00004C32 E8B6060000          <1> 	call	setimod
  3900                              <1> 		; jsr r0,setimod / indicates 
  3901                              <1> 		;	       ; / i-node has been modified
  3902 00004C37 58                  <1> 	pop	eax ; 2nd argument
  3903                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  3904                              <1> 		       ; / (u.off put on stack with 2nd arg)
  3905 00004C38 C3                  <1> 	retn
  3906                              <1> 		; rts r0
  3907                              <1> 
  3908                              <1> ;;arg:  ; < get system call arguments >
  3909                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  3910                              <1> 	; of form:
  3911                              <1> 	;	sys 'routine' ; arg1
  3912                              <1> 	;		or
  3913                              <1> 	;	sys 'routine' ; arg1 ; arg2
  3914                              <1> 	;		or
  3915                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  3916                              <1> 	;	
  3917                              <1> 	; INPUTS ->
  3918                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  3919                              <1> 	;	This pointers's value is actually the value of
  3920                              <1> 	;	update pc at the the trap to sysent (unkni) is
  3921                              <1> 	;	made to process the sys instruction
  3922                              <1> 	;    r0 - contains the return address for the routine
  3923                              <1> 	;	that called arg. The data in the word pointer 
  3924                              <1> 	;	to by the return address is used as address
  3925                              <1> 	;	in which the extracted argument is stored   		
  3926                              <1> 	;    	
  3927                              <1> 	; OUTPUTS ->
  3928                              <1> 	;    'address' - contains the extracted argument 
  3929                              <1> 	;    u.sp+18 - is incremented by 2 
  3930                              <1> 	;    r1 - contains the extracted argument
  3931                              <1> 	;    r0 - points to the next instruction to be
  3932                              <1> 	;	 executed in the calling routine.
  3933                              <1> 	;
  3934                              <1>   
  3935                              <1> 	; mov u.sp,r1
  3936                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  3937                              <1> 			; / into argument of arg2
  3938                              <1> 	; add $2,18.(r1) / point pc on stack 
  3939                              <1> 			      ; / to next system argument
  3940                              <1> 	; rts r0
  3941                              <1> 
  3942                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  3943                              <1> 	; 'arg2' takes first argument in system call
  3944                              <1> 	;  (pointer to name of the file) and puts it in location
  3945                              <1> 	;  u.namep; takes second argument and puts it in u.off
  3946                              <1> 	;  and on top of the stack
  3947                              <1> 	;	
  3948                              <1> 	; INPUTS ->
  3949                              <1> 	;    u.sp, r0
  3950                              <1> 	;    	
  3951                              <1> 	; OUTPUTS ->
  3952                              <1> 	;    u.namep
  3953                              <1> 	;    u.off 
  3954                              <1> 	;    u.off pushed on stack
  3955                              <1> 	;    r1
  3956                              <1> 	;
  3957                              <1> 
  3958                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  3959                              <1> 				; / first arg in sys call
  3960                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  3961                              <1> 				; / second arg in sys call
  3962                              <1> 	; mov r0,r1 / r0 points to calling routine
  3963                              <1> 	; mov (sp),r0 / put operation code back in r0
  3964                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  3965                              <1> 			; / on stack
  3966                              <1> 	; jmp (r1) / return to calling routine
  3967                              <1> 
  3968                              <1> syschown: ; < change owner of file >
  3969                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3970                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3971                              <1> 	;
  3972                              <1> 	; 'syschown' changes the owner of the file whose name is given
  3973                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  3974                              <1> 	; changed to 'owner'
  3975                              <1> 	;
  3976                              <1> 	; Calling sequence:
  3977                              <1> 	;	syschown; name; owner
  3978                              <1> 	; Arguments:
  3979                              <1> 	;	name - address of the file name
  3980                              <1> 	;	       terminated by null byte.
  3981                              <1> 	;	owner - (new) owner (number/ID)
  3982                              <1> 	;	
  3983                              <1> 	; Inputs: -
  3984                              <1> 	; Outputs: -
  3985                              <1> 	; ...............................................................
  3986                              <1> 	;				
  3987                              <1> 	; Retro UNIX 8086 v1 modification: 
  3988                              <1> 	;       'syschown' system call has two arguments; so,
  3989                              <1> 	;	* 1st argument, name is pointed to by BX register
  3990                              <1> 	;	* 2nd argument, owner number is in CX register
  3991                              <1> 	;
  3992                              <1> 	; / name; owner
  3993 00004C39 E8B2FFFFFF          <1> 	call	isown
  3994                              <1> 		; jsr r0,isown / get the i-node and check user status
  3995 00004C3E 803D[3E6F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  3996                              <1> 		; tstb u.uid / super user
  3997 00004C45 7418                <1> 	jz	short syschown1
  3998                              <1> 		; beq 2f / yes, 2f
  3999 00004C47 F605[F66B0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4000                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4001                              <1> 	;jnz	error
  4002                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4003 00004C4E 740F                <1> 	jz	short syschown1
  4004                              <1> 	; 'permission denied !'
  4005 00004C50 C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4005 00004C58 0000                <1>
  4006 00004C5A E9C4EEFFFF          <1> 	jmp	error
  4007                              <1> syschown1: ; 2:
  4008                              <1> 	; AL = owner (number/ID)
  4009 00004C5F A2[F96B0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4010                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4011                              <1> 			       ; / in the i-node
  4012 00004C64 E9DAEEFFFF          <1> 	jmp	sysret
  4013                              <1> 	; 1: 
  4014                              <1> 		; jmp sysret4
  4015                              <1> 	; 3:
  4016                              <1> 		; jmp	error
  4017                              <1> 
  4018                              <1> systime: ; / get time of year
  4019                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4020                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4021                              <1> 	;
  4022                              <1> 	; 20/06/2013
  4023                              <1> 	; 'systime' gets the time of the year.
  4024                              <1> 	; The present time is put on the stack.
  4025                              <1> 	;
  4026                              <1> 	; Calling sequence:
  4027                              <1> 	;	systime
  4028                              <1> 	; Arguments: -
  4029                              <1> 	;	
  4030                              <1> 	; Inputs: -
  4031                              <1> 	; Outputs: sp+2, sp+4 - present time
  4032                              <1> 	; ...............................................................
  4033                              <1> 	;	
  4034                              <1> 	; Retro UNIX 8086 v1 modification: 
  4035                              <1> 	;       'systime' system call will return to the user
  4036                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4037                              <1> 	;
  4038                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4039                              <1> 	;	system call for PC compatibility !!		 	
  4040                              <1> 
  4041 00004C69 E8F2E9FFFF          <1> 	call 	epoch
  4042 00004C6E A3[F86E0000]        <1> 	mov 	[u.r0], eax
  4043                              <1> 		; mov s.time,4(sp)
  4044                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4045                              <1> 				   ; / on the stack
  4046                              <1> 		; br sysret4
  4047 00004C73 E9CBEEFFFF          <1> 	jmp	sysret 
  4048                              <1> 
  4049                              <1> sysstime: ; / set time
  4050                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4051                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4052                              <1> 	;
  4053                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4054                              <1> 	;
  4055                              <1> 	; Calling sequence:
  4056                              <1> 	;	sysstime
  4057                              <1> 	; Arguments: -
  4058                              <1> 	;	
  4059                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4060                              <1> 	; Outputs: -
  4061                              <1> 	; ...............................................................
  4062                              <1> 	;	
  4063                              <1> 	; Retro UNIX 8086 v1 modification: 
  4064                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4065                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4066                              <1> 	; 
  4067                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4068                              <1> 	;	to get sysstime system call arguments from the user;
  4069                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4070                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4071                              <1> 	;
  4072                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4073                              <1> 	;	system call for PC compatibility !!	
  4074                              <1> 
  4075 00004C78 803D[3E6F0000]00    <1> 	cmp	byte [u.uid], 0
  4076                              <1> 		; tstb u.uid / is user the super user
  4077                              <1> 	;ja	error
  4078                              <1> 		; bne error4 / no, error
  4079 00004C7F 760F                <1> 	jna	short systime1
  4080                              <1> 	; 'permission denied !'
  4081 00004C81 C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4081 00004C89 0000                <1>
  4082 00004C8B E993EEFFFF          <1> 	jmp	error
  4083                              <1> systime1:
  4084                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4085                              <1> 	; EBX = unix (epoch) time (from user)
  4086 00004C90 89D8                <1> 	mov	eax, ebx
  4087 00004C92 E849EBFFFF          <1> 	call 	set_date_time
  4088                              <1> 		; mov 4(sp),s.time
  4089                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4090 00004C97 E9A7EEFFFF          <1> 	jmp	sysret
  4091                              <1> 		; br sysret4
  4092                              <1> 
  4093                              <1> sysbreak:
  4094                              <1> 	; 18/10/2015
  4095                              <1> 	; 07/10/2015
  4096                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4097                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4098                              <1> 	;
  4099                              <1> 	; 'sysbreak' sets the programs break points. 
  4100                              <1> 	; It checks the current break point (u.break) to see if it is
  4101                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4102                              <1> 	; even address (if it was odd) and the area between u.break
  4103                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4104                              <1> 	; in u.break and control is passed to 'sysret'.
  4105                              <1> 	;
  4106                              <1> 	; Calling sequence:
  4107                              <1> 	;	sysbreak; addr
  4108                              <1> 	; Arguments: -
  4109                              <1> 	;	
  4110                              <1> 	; Inputs: u.break - current breakpoint
  4111                              <1> 	; Outputs: u.break - new breakpoint 
  4112                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4113                              <1> 	; ...............................................................
  4114                              <1> 	;	
  4115                              <1> 	; Retro UNIX 8086 v1 modification:
  4116                              <1> 	;	The user/application program puts breakpoint address
  4117                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4118                              <1> 	; 	(argument transfer method 1)
  4119                              <1> 	;
  4120                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4121                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4122                              <1> 	;  NOTE:
  4123                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4124                              <1> 	;	'u.break' address) of user's memory for original unix's
  4125                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4126                              <1> 
  4127                              <1> 		; mov u.break,r1 / move users break point to r1
  4128                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4129                              <1> 		; blos 1f / yes, 1f
  4130                              <1> 	; 23/06/2015
  4131 00004C9C 8B2D[246F0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4132                              <1> 	;and	ebp, ebp
  4133                              <1> 	;jz	short sysbreak_3 
  4134                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4135                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4136 00004CA2 8B15[F06E0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4137 00004CA8 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4138                              <1> 	; 07/10/2015
  4139 00004CAB 891D[246F0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4140                              <1> 	;
  4141 00004CB1 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4142                              <1> 			   ; with top of user's stack (virtual!)
  4143 00004CB3 7327                <1> 	jnb	short sysbreak_3
  4144                              <1> 		; cmp r1,sp / is it the same or higher 
  4145                              <1> 			  ; / than the stack?
  4146                              <1> 		; bhis 1f / yes, 1f
  4147 00004CB5 89DE                <1> 	mov	esi, ebx
  4148 00004CB7 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4149 00004CB9 7621                <1> 	jna	short sysbreak_3 
  4150                              <1> 	;push	ebx
  4151                              <1> sysbreak_1:
  4152 00004CBB 89EB                <1> 	mov	ebx, ebp  
  4153 00004CBD E812E5FFFF          <1> 	call	get_physical_addr ; get physical address
  4154 00004CC2 0F82ACFEFFFF        <1> 	jc	tr_addr_nm_err
  4155                              <1> 	; 18/10/2015
  4156 00004CC8 89C7                <1> 	mov	edi, eax 
  4157 00004CCA 29C0                <1> 	sub	eax, eax ; 0
  4158                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4159 00004CCC 39CE                <1> 	cmp	esi, ecx
  4160 00004CCE 7302                <1> 	jnb	short sysbreak_2
  4161 00004CD0 89F1                <1> 	mov	ecx, esi
  4162                              <1> sysbreak_2:
  4163 00004CD2 29CE                <1> 	sub	esi, ecx
  4164 00004CD4 01CD                <1> 	add	ebp, ecx
  4165 00004CD6 F3AA                <1> 	rep 	stosb
  4166 00004CD8 09F6                <1> 	or	esi, esi
  4167 00004CDA 75DF                <1> 	jnz	short sysbreak_1
  4168                              <1> 	;
  4169                              <1> 		; bit $1,r1 / is it an odd address
  4170                              <1> 		; beq 2f / no, its even
  4171                              <1> 		; clrb (r1)+ / yes, make it even
  4172                              <1> 	; 2: / clear area between the break point and the stack
  4173                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4174                              <1> 		; bhis 1f / yes, quit
  4175                              <1> 		; clr (r1)+ / clear word
  4176                              <1> 		; br 2b / go back
  4177                              <1> 	;pop	ebx
  4178                              <1> sysbreak_3: ; 1:
  4179                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4180                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4181                              <1> 			; / in u.break (set new break point)
  4182                              <1> 		; br sysret4 / br sysret
  4183 00004CDC E962EEFFFF          <1> 	jmp	sysret
  4184                              <1> 
  4185                              <1> maknod: 
  4186                              <1> 	; 12/02/2022
  4187                              <1> 	; 03/02/2022
  4188                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4189                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4190                              <1> 	;
  4191                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4192                              <1> 	; for this i-node in the current directory.
  4193                              <1> 	;
  4194                              <1> 	; INPUTS ->
  4195                              <1> 	;    r1 - contains mode
  4196                              <1> 	;    ii - current directory's i-number	
  4197                              <1> 	;    	
  4198                              <1> 	; OUTPUTS ->
  4199                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4200                              <1> 	;    i.flgs - flags in new i-node 
  4201                              <1> 	;    i.uid - filled with u.uid
  4202                              <1> 	;    i.nlks - 1 is put in the number of links
  4203                              <1> 	;    i.ctim - creation time				
  4204                              <1> 	;    i.ctim+2 - modification time
  4205                              <1> 	;    imod - set via call to setimod
  4206                              <1> 	;	
  4207                              <1> 	; ((AX = R1)) input
  4208                              <1> 	;
  4209                              <1> 	; (Retro UNIX Prototype : 
  4210                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4211                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4212                              <1> 
  4213                              <1> 	; / r1 contains the mode
  4214 00004CE1 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4215                              <1> 		; bis $100000,r1 / allocate flag set
  4216 00004CE4 6650                <1> 	push	ax ; *
  4217                              <1> 		; mov r1,-(sp) / put mode on stack
  4218                              <1> 	; 31/07/2013
  4219 00004CE6 66A1[DA6E0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4220                              <1> 		; mov ii,r1 / move current i-number to r1
  4221 00004CEC B201                <1> 	mov	dl, 1 ; owner flag mask
  4222 00004CEE E8C4050000          <1> 	call	access	
  4223                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4224                              <1> 	; 03/02/2022
  4225 00004CF3 50                  <1> 	push	eax ; **
  4226                              <1> 	;push	ax
  4227                              <1> 		; mov r1,-(sp) / put i-number on stack
  4228 00004CF4 66B82800            <1> 	mov	ax, 40
  4229                              <1> 		; mov $40.,r1 / r1 = 40
  4230                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4231 00004CF8 6640                <1> 	inc	ax
  4232                              <1> 		; inc r1 / r1 = r1 + 1
  4233 00004CFA E87D060000          <1> 	call	imap
  4234                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4235                              <1> 			    ; /	inode map in r2 & m
  4236                              <1>   
  4237                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4238                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4239                              <1> 
  4240                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4241                              <1> 	;	       Inode count must be checked here
  4242                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4243                              <1> 
  4244                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4245                              <1> 	; (inode count check)
  4246                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4247                              <1> 
  4248 00004CFF 730F                <1> 	jnc	short maknod2
  4249                              <1> 
  4250                              <1> 	; no free inode in inode table !
  4251 00004D01 C705[476F0000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4251 00004D09 0000                <1>
  4252                              <1> 			; miscellaneous/other errors
  4253 00004D0B E913EEFFFF          <1> 	jmp	error	
  4254                              <1> maknod2: 	
  4255 00004D10 8413                <1> 	test	[ebx], dl
  4256                              <1> 		; bitb mq,(r2) / is the i-node active
  4257 00004D12 75E4                <1> 	jnz	short maknod1
  4258                              <1> 		; bne 1b / yes, try the next one
  4259 00004D14 0813                <1> 	or	[ebx], dl
  4260                              <1> 		; bisb mq,(r2) / no, make it active 
  4261                              <1> 			     ; / (put a 1 in the bit map)
  4262 00004D16 E8C8040000          <1> 	call	iget
  4263                              <1> 		; jsr r0,iget / get i-node into core
  4264                              <1> 	; 03/02/2022
  4265 00004D1B F605[F76B0000]80    <1> 	test	byte [i.flgs+1], 80h
  4266                              <1> 	;test	word [i.flgs], 8000h 
  4267                              <1> 		; tst i.flgs / is i-node already allocated
  4268 00004D22 75D4                <1> 	jnz	short maknod1	
  4269                              <1> 		; blt 1b / yes, look for another one
  4270 00004D24 66A3[2A6F0000]      <1> 	mov	[u.dirbuf], ax
  4271                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4272                              <1> 	; 03/02/2022
  4273 00004D2A 58                  <1> 	pop	eax ; **
  4274                              <1> 	;pop	ax
  4275                              <1> 		; mov (sp)+,r1 / get current i-number back
  4276 00004D2B E8B3040000          <1> 	call	iget
  4277                              <1> 		; jsr r0,iget / get i-node in core
  4278 00004D30 E8AAF7FFFF          <1> 	call	mkdir
  4279                              <1> 		; jsr r0,mkdir / make a directory entry 
  4280                              <1> 			     ; / in current directory
  4281 00004D35 66A1[2A6F0000]      <1> 	mov	ax, [u.dirbuf]
  4282                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4283 00004D3B E8A3040000          <1> 	call	iget
  4284                              <1> 		; jsr r0,iget / get it into core
  4285                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4286                              <1> 	;mov	ecx, 8
  4287                              <1> 	; 03/02/2022 
  4288 00004D40 29C9                <1> 	sub	ecx, ecx
  4289 00004D42 B108                <1> 	mov	cl, 8
  4290 00004D44 31C0                <1> 	xor	eax, eax ; 0
  4291 00004D46 BF[F66B0000]        <1> 	mov	edi, inode 
  4292 00004D4B F3AB                <1> 	rep	stosd
  4293                              <1> 	;
  4294 00004D4D 668F05[F66B0000]    <1> 	pop	word [i.flgs] ; *
  4295                              <1> 		; mov (sp)+,i.flgs / fill flags
  4296 00004D54 8A0D[3E6F0000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4297 00004D5A 880D[F96B0000]      <1> 	mov 	[i.uid], cl
  4298                              <1> 		; movb u.uid,i.uid / user id	
  4299 00004D60 C605[F86B0000]01    <1> 	mov     byte [i.nlks], 1
  4300                              <1> 		; movb $1,i.nlks / 1 link
  4301                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4302                              <1> 	;mov	eax, [s.time]
  4303                              <1> 	;mov 	[i.ctim], eax
  4304                              <1> 	 	; mov s.time,i.ctim / time created
  4305                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4306                              <1> 	; Retro UNIX 8086 v1 modification !
  4307                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4308                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4309                              <1> 	;call setimod
  4310                              <1> 		; jsr r0,setimod / set modified flag
  4311                              <1> 	;retn
  4312                              <1> 		; rts r0 / return
  4313                              <1> 	; 03/02/2022
  4314 00004D67 E981050000          <1> 	jmp	setimod
  4315                              <1> 
  4316                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4317                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4318                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4319                              <1> 	;
  4320                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4321                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4322                              <1> 	; The file descriptor refers to a file open for reading or
  4323                              <1> 	; writing. The read (or write) pointer is set as follows:
  4324                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4325                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4326                              <1> 	;	  current location plus offset.
  4327                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4328                              <1> 	;	  size of file plus offset.
  4329                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4330                              <1> 	;
  4331                              <1> 	; Calling sequence:
  4332                              <1> 	;	sysseek; offset; ptrname
  4333                              <1> 	; Arguments:
  4334                              <1> 	;	offset - number of bytes desired to move 
  4335                              <1> 	;		 the r/w pointer
  4336                              <1> 	;	ptrname - a switch indicated above
  4337                              <1> 	;
  4338                              <1> 	; Inputs: r0 - file descriptor 
  4339                              <1> 	; Outputs: -
  4340                              <1> 	; ...............................................................
  4341                              <1> 	;	
  4342                              <1> 	; Retro UNIX 8086 v1 modification: 
  4343                              <1> 	;       'sysseek' system call has three arguments; so,
  4344                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4345                              <1> 	;	* 2nd argument, offset is in CX register
  4346                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4347                              <1> 	;	
  4348                              <1> 
  4349 00004D6C E822000000          <1> 	call	seektell
  4350                              <1> 	; AX = u.count
  4351                              <1> 	; BX = *u.fofp
  4352                              <1> 		; jsr r0,seektell / get proper value in u.count
  4353                              <1> 		; add u.base,u.count / add u.base to it
  4354 00004D71 0305[186F0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4355 00004D77 8903                <1> 	mov	[ebx], eax
  4356                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4357 00004D79 E9C5EDFFFF          <1> 	jmp	sysret
  4358                              <1> 		; br sysret4
  4359                              <1> 
  4360                              <1> systell: ; / get the r/w pointer
  4361                              <1> 	; 03/02/2022
  4362                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4363                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4364                              <1> 	;
  4365                              <1> 	; Retro UNIX 8086 v1 modification:
  4366                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4367                              <1> 	; 	    it returns with error !
  4368                              <1> 	; Inputs: r0 - file descriptor 
  4369                              <1> 	; Outputs: r0 - file r/w pointer
  4370                              <1> 
  4371                              <1> 	;xor	ecx, ecx ; 0
  4372                              <1> 	;mov	edx, 1 ; 05/08/2013
  4373                              <1> 	; 03/02/2022
  4374 00004D7E 29D2                <1> 	sub	edx, edx
  4375 00004D80 FEC2                <1> 	inc	dl
  4376                              <1> 	; edx = 1
  4377                              <1> 	;call 	seektell
  4378 00004D82 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4379                              <1> 	;mov	ebx, [u.fofp]
  4380 00004D87 8B03                <1> 	mov	eax, [ebx]
  4381 00004D89 A3[F86E0000]        <1> 	mov	[u.r0], eax
  4382 00004D8E E9B0EDFFFF          <1> 	jmp	sysret
  4383                              <1> 
  4384                              <1> ; Original unix v1 'systell' system call:
  4385                              <1> 		; jsr r0,seektell
  4386                              <1> 		; br error4
  4387                              <1> 
  4388                              <1> seektell:
  4389                              <1> 	; 03/02/2022
  4390                              <1> 	; 03/01/2016
  4391                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4392                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4393                              <1> 	;
  4394                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4395                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4396                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4397                              <1> 	; getf. The i-node is brought into core and then u.count
  4398                              <1> 	; is checked to see it is a 0, 1, or 2.
  4399                              <1> 	; If it is 0 - u.count stays the same
  4400                              <1> 	;          1 - u.count = offset (u.fofp)
  4401                              <1> 	;	   2 - u.count = i.size (size of file)
  4402                              <1> 	; 	 		
  4403                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4404                              <1> 	;	Argument 1, file descriptor is in BX;
  4405                              <1> 	;	Argument 2, offset is in CX;
  4406                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4407                              <1> 	;
  4408                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4409                              <1> 	; call 	arg
  4410                              <1> 	;
  4411                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4412                              <1> 	;
  4413 00004D93 890D[186F0000]      <1> 	mov 	[u.base], ecx ; offset
  4414                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4415                              <1> seektell0:
  4416 00004D99 8915[1C6F0000]      <1> 	mov 	[u.count], edx
  4417                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4418                              <1> 	; mov	ax, bx
  4419                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4420                              <1> 			     ; / (index in u.fp list)
  4421                              <1> 	; call	getf
  4422                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4423                              <1> 	; BX = file descriptor (file number)
  4424 00004D9F E842FCFFFF          <1> 	call	getf1
  4425                              <1> 	; 03/02/2022
  4426 00004DA4 09C0                <1> 	or	eax, eax
  4427                              <1> 	;or	ax, ax ; i-number of the file
  4428                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4429                              <1> 		             ; / put it on the stack
  4430                              <1> 	;jz	error
  4431                              <1> 		; beq error4 / if i-number is 0, not active so error
  4432 00004DA6 750F                <1> 	jnz	short seektell1
  4433 00004DA8 C705[476F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4433 00004DB0 0000                <1>
  4434 00004DB2 E96CEDFFFF          <1> 	jmp	error
  4435                              <1> seektell1:
  4436                              <1> 	;push	eax
  4437 00004DB7 80FC80              <1> 	cmp	ah, 80h
  4438 00004DBA 7203                <1> 	jb	short seektell2
  4439                              <1> 		; bgt .+4 / if its positive jump
  4440 00004DBC 66F7D8              <1> 	neg	ax
  4441                              <1> 		; neg r1 / if not make it positive
  4442                              <1> seektell2:
  4443 00004DBF E81F040000          <1> 	call	iget
  4444                              <1> 		; jsr r0,iget / get its i-node into core
  4445 00004DC4 8B1D[086F0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4446 00004DCA 803D[1C6F0000]01    <1> 	cmp	byte [u.count], 1
  4447                              <1> 		; cmp u.count,$1 / is ptr name =1
  4448 00004DD1 7705                <1> 	ja	short seektell3
  4449                              <1> 		; blt 2f / no its zero
  4450 00004DD3 740A                <1> 	je	short seektell_4
  4451                              <1> 		; beq 1f / yes its 1
  4452 00004DD5 31C0                <1> 	xor	eax, eax
  4453                              <1> 	;jmp	short seektell_5
  4454 00004DD7 C3                  <1> 	retn
  4455                              <1> seektell3:
  4456                              <1> 	; 03/01/2016
  4457                              <1> 	;movzx  eax, word [i.size]
  4458 00004DD8 66A1[FA6B0000]      <1> 	mov	ax, [i.size]
  4459                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4460                              <1>                                    ; / in file in u.count
  4461                              <1> 	;jmp	short seektell_5
  4462                              <1> 		; br 2f
  4463 00004DDE C3                  <1> 	retn
  4464                              <1> seektell_4: ; 1: / ptrname =1
  4465                              <1> 	;mov	ebx, [u.fofp]
  4466 00004DDF 8B03                <1> 	mov	eax, [ebx]
  4467                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4468                              <1> ;seektell_5: ; 2: / ptrname =0
  4469                              <1> 	;mov	[u.count], eax
  4470                              <1> 	;pop	eax 
  4471                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4472 00004DE1 C3                  <1> 	retn
  4473                              <1> 		; rts r0
  4474                              <1> 
  4475                              <1> sysintr: ; / set interrupt handling
  4476                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4477                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4478                              <1> 	;
  4479                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4480                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4481                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4482                              <1> 	; If one does the interrupt character in the tty buffer is
  4483                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4484                              <1> 	; 'sysret' is just called.	
  4485                              <1> 	;
  4486                              <1> 	; Calling sequence:
  4487                              <1> 	;	sysintr; arg
  4488                              <1> 	; Argument:
  4489                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4490                              <1> 	;	    - if 1, intterupts cause their normal result
  4491                              <1> 	;		 i.e force an exit.
  4492                              <1> 	;	    - if arg is a location within the program,
  4493                              <1> 	;		control is passed to that location when
  4494                              <1> 	;		an interrupt occurs.	
  4495                              <1> 	; Inputs: -
  4496                              <1> 	; Outputs: -
  4497                              <1> 	; ...............................................................
  4498                              <1> 	;	
  4499                              <1> 	; Retro UNIX 8086 v1 modification: 
  4500                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4501                              <1> 	;	then branches into sysquit.
  4502                              <1> 	;
  4503 00004DE2 66891D[366F0000]    <1> 	mov	[u.intr], bx
  4504                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4505                              <1> 		; br 1f / go into quit routine
  4506 00004DE9 E955EDFFFF          <1> 	jmp	sysret
  4507                              <1> 
  4508                              <1> sysquit:
  4509                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4510                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4511                              <1> 	;
  4512                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4513                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4514                              <1> 	; tty exists. If one does the interrupt character in the tty
  4515                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4516                              <1> 	; 'sysret' is just called.	
  4517                              <1> 	;
  4518                              <1> 	; Calling sequence:
  4519                              <1> 	;	sysquit; arg
  4520                              <1> 	; Argument:
  4521                              <1> 	;	arg - if 0, this call diables quit signals from the
  4522                              <1> 	;		typewriter (ASCII FS)
  4523                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4524                              <1> 	;		cease and a core image to be produced.
  4525                              <1> 	;		 i.e force an exit.
  4526                              <1> 	;	    - if arg is an addres in the program,
  4527                              <1> 	;		a quit causes control to sent to that
  4528                              <1> 	;		location.	
  4529                              <1> 	; Inputs: -
  4530                              <1> 	; Outputs: -
  4531                              <1> 	; ...............................................................
  4532                              <1> 	;	
  4533                              <1> 	; Retro UNIX 8086 v1 modification: 
  4534                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4535                              <1> 	;	then branches into 'sysret'.
  4536                              <1> 	;
  4537 00004DEE 66891D[386F0000]    <1> 	mov	[u.quit], bx
  4538 00004DF5 E949EDFFFF          <1> 	jmp	sysret
  4539                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4540                              <1> 	;1:
  4541                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4542                              <1> 			      ; / to r1
  4543                              <1> 		; beq sysret4 / return to user
  4544                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4545                              <1> 			   ; / in the tty buffer
  4546                              <1> 		; br sysret4 / return to user
  4547                              <1> 
  4548                              <1> syssetuid: ; / set process id
  4549                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4550                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4551                              <1> 	;
  4552                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4553                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4554                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4555                              <1> 	; Only the super user can make this call.	
  4556                              <1> 	;
  4557                              <1> 	; Calling sequence:
  4558                              <1> 	;	syssetuid
  4559                              <1> 	; Arguments: -
  4560                              <1> 	;
  4561                              <1> 	; Inputs: (u.r0) - contains the process id.
  4562                              <1> 	; Outputs: -
  4563                              <1> 	; ...............................................................
  4564                              <1> 	;	
  4565                              <1> 	; Retro UNIX 8086 v1 modification: 
  4566                              <1> 	;       BL contains the (new) user ID of the current process
  4567                              <1> 
  4568                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4569 00004DFA 3A1D[3F6F0000]      <1> 	cmp	bl, [u.ruid] 
  4570                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4571                              <1> 			       ; / id number
  4572 00004E00 741E                <1> 	je	short setuid1
  4573                              <1> 		; beq 1f / yes
  4574 00004E02 803D[3E6F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4575                              <1> 		; tstb u.uid / no, is current user the super user?
  4576                              <1> 	;ja	error
  4577                              <1> 		; bne error4 / no, error
  4578 00004E09 760F                <1> 	jna	short setuid0
  4579 00004E0B C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4579 00004E13 0000                <1>
  4580                              <1> 				; 'permission denied !' error
  4581 00004E15 E909EDFFFF          <1> 	jmp	error
  4582                              <1> setuid0:
  4583 00004E1A 881D[3F6F0000]      <1> 	mov	[u.ruid], bl
  4584                              <1> setuid1: ; 1:
  4585 00004E20 881D[3E6F0000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4586                              <1> 		; movb r1,u.uid / put process id in u.uid
  4587                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4588 00004E26 E918EDFFFF          <1> 	jmp	sysret
  4589                              <1> 		; br sysret4 / system return
  4590                              <1> 
  4591                              <1> sysgetuid: ; < get user id >
  4592                              <1> 	; 03/02/2022
  4593                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4594                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4595                              <1> 	;
  4596                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4597                              <1> 	; The real user ID identifies the person who is logged in,
  4598                              <1> 	; in contradistinction to the effective user ID, which
  4599                              <1> 	; determines his access permission at each moment. It is thus
  4600                              <1> 	; useful to programs which operate using the 'set user ID'
  4601                              <1> 	; mode, to find out who invoked them.	
  4602                              <1> 	;
  4603                              <1> 	; Calling sequence:
  4604                              <1> 	;	syssetuid
  4605                              <1> 	; Arguments: -
  4606                              <1> 	;
  4607                              <1> 	; Inputs: -
  4608                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4609                              <1> 	; ...............................................................
  4610                              <1> 	;	
  4611                              <1> 	; Retro UNIX 8086 v1 modification: 
  4612                              <1> 	;       AL contains the real user ID at return.
  4613                              <1> 	;
  4614                              <1> 	;movzx 	eax, byte [u.ruid]
  4615                              <1> 	; 03/03/2022
  4616 00004E2B A0[3F6F0000]        <1> 	mov	al, [u.ruid]
  4617 00004E30 A3[F86E0000]        <1> 	mov	[u.r0], eax
  4618                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4619 00004E35 E909EDFFFF          <1> 	jmp	sysret
  4620                              <1> 		; br sysret4 / systerm return, sysret
  4621                              <1> 
  4622                              <1> anyi: 
  4623                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4624                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4625                              <1> 	;
  4626                              <1> 	; 'anyi' is called if a file deleted while open.
  4627                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4628                              <1> 	;
  4629                              <1> 	; INPUTS ->
  4630                              <1> 	;    r1 - contains an i-number
  4631                              <1> 	;    fsp - start of table containing open files
  4632                              <1> 	;
  4633                              <1> 	; OUTPUTS ->
  4634                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4635                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4636                              <1> 	;    if file not found - bit in i-node map is cleared
  4637                              <1> 	;    			 (i-node is freed)
  4638                              <1> 	;               all blocks related to i-node are freed
  4639                              <1> 	;	        all flags in i-node are cleared
  4640                              <1> 	; ((AX = R1)) input
  4641                              <1> 	;
  4642                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4643                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4644                              <1> 	;
  4645                              <1> 		; / r1 contains an i-number
  4646 00004E3A BB[C66C0000]        <1> 	mov	ebx, fsp
  4647                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4648                              <1> anyi_1: ; 1:
  4649 00004E3F 663B03              <1> 	cmp	ax, [ebx]
  4650                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4651 00004E42 7433                <1> 	je	short anyi_3
  4652                              <1> 		; beq 1f / yes, 1f
  4653 00004E44 66F7D8              <1> 	neg	ax
  4654                              <1> 		; neg r1 / no complement r1
  4655 00004E47 663B03              <1> 	cmp	ax, [ebx]
  4656                              <1> 		; cmp r1,(r2) / do they match now?
  4657 00004E4A 742B                <1> 	je	short anyi_3
  4658                              <1> 		; beq 1f / yes, transfer
  4659                              <1> 		; / i-numbers do not match
  4660 00004E4C 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4661                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4662                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4663 00004E4F 81FB[BA6E0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4664                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4665                              <1> 				; / are we at last entry in the table
  4666 00004E55 72E8                <1> 	jb	short anyi_1
  4667                              <1> 		; blt 1b / no, check next entries i-number
  4668                              <1> 	;cmp	ax, 32768
  4669 00004E57 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4670                              <1> 		; tst r1 / yes, no match
  4671                              <1> 		; bge .+4
  4672 00004E5A 7203                <1> 	jb	short anyi_2
  4673 00004E5C 66F7D8              <1> 	neg	ax
  4674                              <1> 		; neg r1 / make i-number positive
  4675                              <1> anyi_2:	
  4676 00004E5F E818050000          <1> 	call	imap
  4677                              <1> 		; jsr r0,imap / get address of allocation bit 
  4678                              <1> 			    ; / in the i-map in r2
  4679                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4680                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4681                              <1>  	; not	dx
  4682 00004E64 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4683                              <1>         ;and	[ebx], dx
  4684 00004E66 2013                <1> 	and 	[ebx], dl 
  4685                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4686 00004E68 E8A2040000          <1> 	call	itrunc
  4687                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4688 00004E6D 66C705[F66B0000]00- <1>  	mov 	word [i.flgs], 0
  4688 00004E75 00                  <1>
  4689                              <1> 		; clr i.flgs / clear all flags in the i-node
  4690 00004E76 C3                  <1> 	retn
  4691                              <1> 		;rts	r0 / return
  4692                              <1> anyi_3: ; 1: / i-numbers match
  4693 00004E77 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4694                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4695                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4696 00004E7A C3                  <1> 	retn
  4697                              <1> 		; rts r0
  1991                                  %include 'u3.s'        ; 10/05/2015
  1992                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  1993                              <1> ; Last Modification: 03/02/2022
  1994                              <1> ; ----------------------------------------------------------------------------
  1995                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1996                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1997                              <1> ;
  1998                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  1999                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2000                              <1> ; <Bell Laboratories (17/3/1972)>
  2001                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2002                              <1> ;
  2003                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2004                              <1> ;
  2005                              <1> ; ****************************************************************************
  2006                              <1> ; 15/09/2015
  2007                              <1> 
  2008                              <1> tswitch: ; Retro UNIX 386 v1
  2009                              <1> tswap:
  2010                              <1> 	; 01/09/2015
  2011                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2012                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2013                              <1> 	; time out swap, called when a user times out.
  2014                              <1> 	; the user is put on the low priority queue.
  2015                              <1> 	; This is done by making a link from the last user
  2016                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2017                              <1> 	; then he is swapped out.
  2018                              <1> 	;
  2019                              <1> 	; Retro UNIX 386 v1 modification ->
  2020                              <1> 	;       swap (software task switch) is performed by changing
  2021                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2022                              <1> 	;	as in Retro UNIX 8086 v1.
  2023                              <1> 	;
  2024                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2025                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2026                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2027                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2028                              <1> 	;	compatibles was using 1MB segmented memory 
  2029                              <1> 	;	in 8086/8088 times.
  2030                              <1> 	;
  2031                              <1> 	; INPUTS ->
  2032                              <1> 	;    u.uno - users process number
  2033                              <1> 	;    runq+4 - lowest priority queue
  2034                              <1> 	; OUTPUTS ->
  2035                              <1> 	;    r0 - users process number
  2036                              <1> 	;    r2 - lowest priority queue address
  2037                              <1> 	;
  2038                              <1> 	; ((AX = R0, BX = R2)) output
  2039                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2040                              <1> 	;
  2041 00004E7B A0[416F0000]        <1> 	mov 	al, [u.uno]
  2042                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2043                              <1> 		; mov  $runq+4,r2 
  2044                              <1> 			; / move lowest priority queue address to r2
  2045 00004E80 E8CD000000          <1>         call 	putlu
  2046                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2047                              <1> 		             ; / u.uno's user
  2048                              <1> 
  2049                              <1> switch: ; Retro UNIX 386 v1
  2050                              <1> swap:
  2051                              <1> 	; 03/02/2022
  2052                              <1> 	; 02/09/2015
  2053                              <1> 	; 01/09/2015
  2054                              <1> 	; 31/08/2015
  2055                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2056                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2057                              <1> 	; 'swap' is routine that controls the swapping of processes
  2058                              <1> 	; in and out of core.
  2059                              <1> 	;
  2060                              <1> 	; Retro UNIX 386 v1 modification ->
  2061                              <1> 	;       swap (software task switch) is performed by changing
  2062                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2063                              <1> 	;	as in Retro UNIX 8086 v1.
  2064                              <1> 	;
  2065                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2066                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2067                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2068                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2069                              <1> 	;	compatibles was using 1MB segmented memory 
  2070                              <1> 	;	in 8086/8088 times.
  2071                              <1> 	;
  2072                              <1> 	; INPUTS ->
  2073                              <1> 	;    runq table - contains processes to run.
  2074                              <1> 	;    p.link - contains next process in line to be run.
  2075                              <1> 	;    u.uno - process number of process in core	
  2076                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2077                              <1> 	; OUTPUTS ->
  2078                              <1> 	;    (original unix v1 -> present process to its disk block)
  2079                              <1> 	;    (original unix v1 -> new process into core -> 
  2080                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2081                              <1> 	;	   for new process)
  2082                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2083                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2084                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2085                              <1> 	;	 for now, it will swap the process if there is not
  2086                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2087                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2088                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2089                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2090                              <1> 	;
  2091                              <1> 	;    u.pri -points to highest priority run Q.
  2092                              <1> 	;    r2 - points to the run queue.
  2093                              <1> 	;    r1 - contains new process number
  2094                              <1> 	;    r0 - points to place in routine or process that called
  2095                              <1> 	;	  swap all user parameters
  2096                              <1> 	;				
  2097                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2098                              <1> 	;
  2099                              <1> swap_0:
  2100                              <1> 		;mov $300,*$ps / processor priority = 6
  2101 00004E85 BE[EA6E0000]        <1> 	mov	esi, runq
  2102                              <1> 		; mov $runq,r2 / r2 points to runq table
  2103                              <1> swap_1: ; 1: / search runq table for highest priority process
  2104 00004E8A 668B06              <1> 	mov	ax, [esi]
  2105 00004E8D 6621C0              <1> 	and 	ax, ax
  2106                              <1>        		; tst (r2)+ / are there any processes to run 
  2107                              <1> 			  ; / in this Q entry
  2108 00004E90 7507                <1> 	jnz	short swap_2
  2109                              <1>        		; bne 1f / yes, process 1f
  2110                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2111                              <1> 			       ; / to end of table
  2112                              <1> 		; bne 1b / if not at end, go back
  2113 00004E92 E8E0000000          <1> 	call	idle
  2114                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2115                              <1> 				       ; / all queues are empty
  2116 00004E97 EBF1                <1> 	jmp	short swap_1
  2117                              <1> 		; br swap
  2118                              <1> swap_2: ; 1:
  2119 00004E99 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2120                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2121                              <1>  		; mov r2,u.pri / set present user to this run queue
  2122                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2123 00004E9C 38E0                <1> 	cmp	al, ah
  2124                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2125                              <1> 			      ; / in this Q to be run
  2126 00004E9E 740A                <1> 	je	short swap_3
  2127                              <1>        		; beq 1f / yes
  2128                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2129                              <1> 	;movzx	ebx, al
  2130 00004EA0 8AA3[656C0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2131 00004EA6 8826                <1>        	mov	[esi], ah
  2132                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2133                              <1> 				       ; / in line into run queue
  2134 00004EA8 EB05                <1> 	jmp	short swap_4
  2135                              <1>        		; br 2f
  2136                              <1> swap_3: ; 1:
  2137                              <1> 	;xor	dx, dx
  2138                              <1> 	; 03/02/2022
  2139 00004EAA 31D2                <1> 	xor	edx, edx
  2140 00004EAC 668916              <1> 	mov	[esi], dx
  2141                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2142                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2143                              <1>       ; / in new process if required
  2144                              <1>        		; clr *$ps / clear processor status
  2145 00004EAF 8A25[416F0000]      <1> 	mov 	ah, [u.uno]
  2146 00004EB5 38C4                <1> 	cmp	ah, al
  2147                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2148                              <1> 			      ; / the process in core?
  2149 00004EB7 743B                <1>        	je	short swap_8
  2150                              <1>        		; beq 2f / yes, don't have to swap
  2151                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2152                              <1> 			   ; / (address in routine that called swap)
  2153                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2154                              <1> 	; 01/09/2015
  2155                              <1> 	;mov	[u.usp], esp
  2156                              <1>        		; mov sp,u.usp / save stack pointer
  2157                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2158                              <1> 			       ; / to the stack pointer
  2159 00004EB9 08E4                <1> 	or	ah, ah
  2160                              <1>        		; tstb u.uno / is the process # = 0
  2161 00004EBB 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2162                              <1> 		; beq  1f / yes, kill process by overwriting
  2163                              <1> 	; 02/09/2015
  2164 00004EBD 8925[F46E0000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2165                              <1> 	;
  2166 00004EC3 E834000000          <1> 	call	wswap
  2167                              <1> 		;jsr r0,wswap / write out core to disk
  2168                              <1> 	 ; 31/08/2015
  2169                              <1> 	;movzx	ebx, al ; New (running) process number
  2170 00004EC8 EB1C                <1> 	jmp 	short swap_7
  2171                              <1> swap_6:
  2172                              <1> 	; 31/08/2015
  2173                              <1> 	; Deallocate memory pages belong to the process
  2174                              <1> 	; which is being terminated
  2175                              <1> 	; 14/05/2015 ('sysexit')
  2176                              <1>  	; Deallocate memory pages of the process
  2177                              <1> 	; (Retro UNIX 386 v1 modification !)
  2178                              <1> 	;
  2179                              <1> 	; movzx ebx, al
  2180 00004ECA 53                  <1> 	push	ebx
  2181 00004ECB A1[4B6F0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2182 00004ED0 8B1D[4F6F0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2183 00004ED6 E83DE0FFFF          <1> 	call	deallocate_page_dir
  2184 00004EDB A1[426F0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2185 00004EE0 E8CBE0FFFF          <1> 	call	deallocate_page
  2186 00004EE5 5B                  <1> 	pop	ebx
  2187                              <1> swap_7: ;1: 
  2188                              <1> 	; 02/09/2015
  2189                              <1> 	; 31/08/2015
  2190                              <1> 	; 14/05/2015
  2191 00004EE6 C0E302              <1> 	shl	bl, 2 ; * 4 
  2192 00004EE9 8B83[826C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2193                              <1> 	;cli
  2194 00004EEF E831000000          <1> 	call	rswap
  2195                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2196                              <1> 		; jsr r0,rswap / read new process into core
  2197                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2198                              <1> 			      ; / to his program to its normal
  2199                              <1> 	; 01/09/2015
  2200                              <1> 	;mov	esp, [u.usp]	
  2201                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2202                              <1> 			     ; / new process stack
  2203                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2204                              <1> 			     ; / that just got swapped in, left off.,
  2205                              <1> 			     ; / i.e., transfer control to new process
  2206                              <1> 	;sti
  2207                              <1> swap_8: ;2:
  2208                              <1> 	; RETRO UNIX 8086 v1 modification !
  2209 00004EF4 C605[346F0000]04    <1> 	mov	byte [u.quant], time_count 
  2210                              <1> 		; movb    $30.,uquant / initialize process time quantum
  2211 00004EFB C3                  <1> 	retn
  2212                              <1> 		; rts r0 / return
  2213                              <1> 
  2214                              <1> wswap:  ; < swap out, swap to disk >
  2215                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2216                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2217                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2218                              <1> 	; appropriate disk area.
  2219                              <1> 	;
  2220                              <1> 	; Retro UNIX 386 v1 modification ->
  2221                              <1> 	;       User (u) structure content and the user's register content
  2222                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2223                              <1> 	;	saving 'u' structure and user registers for task switching).
  2224                              <1> 	;	u.usp - points to kernel stack address which contains
  2225                              <1> 	;		user's registers while entering system call.  
  2226                              <1> 	;	u.sp  - points to kernel stack address 
  2227                              <1> 	;		to return from system call -for IRET-.
  2228                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2229                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2230                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2231                              <1> 	;
  2232                              <1> 	; Retro UNIX 8086 v1 modification ->
  2233                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2234                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2235                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2236                              <1> 	;	compatibles was using 1MB segmented memory 
  2237                              <1> 	;	in 8086/8088 times.
  2238                              <1> 	;
  2239                              <1> 	; INPUTS ->
  2240                              <1> 	;    u.break - points to end of program
  2241                              <1> 	;    u.usp - stack pointer at the moment of swap
  2242                              <1> 	;    core - beginning of process program		
  2243                              <1> 	;    ecore - end of core 	
  2244                              <1> 	;    user - start of user parameter area		
  2245                              <1> 	;    u.uno - user process number	
  2246                              <1> 	;    p.dska - holds block number of process	
  2247                              <1> 	; OUTPUTS ->
  2248                              <1> 	;    swp I/O queue
  2249                              <1> 	;    p.break - negative word count of process 
  2250                              <1> 	;    r1 - process disk address	
  2251                              <1> 	;    r2 - negative word count
  2252                              <1> 	;
  2253                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2254                              <1> 	;
  2255                              <1> 	; INPUTS ->
  2256                              <1> 	;    u.uno - process number (to be swapped out)
  2257                              <1> 	; OUTPUTS ->
  2258                              <1> 	;    none
  2259                              <1> 	;
  2260                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2261                              <1> 	;
  2262 00004EFC 8B3D[426F0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2263 00004F02 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2264 00004F07 BE[F06E0000]        <1> 	mov	esi, user ; active user (u) structure	
  2265 00004F0C F3A5                <1> 	rep	movsd
  2266                              <1> 	;
  2267 00004F0E 8B35[F46E0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2268                              <1> 			     ;      points to user registers)
  2269 00004F14 8B0D[F06E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2270                              <1> 			     ; (for IRET)
  2271                              <1> 			     ; [u.sp] -> EIP (user)
  2272                              <1> 			     ; [u.sp+4]-> CS (user)
  2273                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2274                              <1> 			     ; [u.sp+12] -> ESP (user)
  2275                              <1> 			     ; [u.sp+16] -> SS (user)	
  2276 00004F1A 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2277 00004F1C 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2278                              <1> 			     ; (for IRET) 	
  2279 00004F1F C1E902              <1> 	shr	ecx, 2	     		
  2280 00004F22 F3A5                <1> 	rep	movsd
  2281 00004F24 C3                  <1> 	retn
  2282                              <1> 
  2283                              <1> 	; Original UNIX v1 'wswap' routine:
  2284                              <1> 	; wswap:
  2285                              <1> 		; mov *$30,u.emt / determines handling of emts
  2286                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2287                              <1> 				; / illegal instructions
  2288                              <1> 		; mov u.break,r2 / put process program break address in r2
  2289                              <1> 		; inc r2 / add 1 to it 
  2290                              <1> 		; bic $1,r2 / make it even
  2291                              <1> 		; mov r2,u.break / set break to an even location
  2292                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2293                              <1> 			     ; / at moment of swap in r3
  2294                              <1> 		; cmp r2,$core / is u.break less than $core
  2295                              <1> 		; blos 2f / yes
  2296                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2297                              <1>        		; bhis 2f / yes
  2298                              <1> 	; 1:
  2299                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2300                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2301                              <1> 		; bne 1b / no, keep packing
  2302                              <1> 	 	; br 1f / yes
  2303                              <1> 	; 2:
  2304                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2305                              <1> 	; 1:
  2306                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2307                              <1> 			   ; / (user up to end of stack gets written out)
  2308                              <1> 		; neg r2 / make it negative
  2309                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2310                              <1> 		; mov r2,swp+4 / word count
  2311                              <1> 		; movb u.uno,r1 / move user process number to r1
  2312                              <1> 		; asl r1 / x2 for index
  2313                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2314                              <1> 				     ; / into the p.break table
  2315                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2316                              <1> 				    ; /	for process to r1
  2317                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2318                              <1> 			     ; / (block number)
  2319                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2320                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2321                              <1> 	; 1:
  2322                              <1>        		; tstb swp+1 / is lt done writing?
  2323                              <1>        		; bne 1b / no, wait
  2324                              <1> 		; rts r0 / yes, return to swap
  2325                              <1> 
  2326                              <1> rswap:  ; < swap in, swap from disk >
  2327                              <1> 	; 15/09/2015
  2328                              <1> 	; 28/08/2015
  2329                              <1> 	; 14/05/2015
  2330                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2331                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2332                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2333                              <1> 	; from disk into core.
  2334                              <1> 	;
  2335                              <1> 	; Retro UNIX 386 v1 modification ->
  2336                              <1> 	;       User (u) structure content and the user's register content
  2337                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2338                              <1> 	;	saving 'u' structure and user registers for task switching).
  2339                              <1> 	;	u.usp - points to kernel stack address which contains
  2340                              <1> 	;		user's registers while entering system call.  
  2341                              <1> 	;	u.sp  - points to kernel stack address 
  2342                              <1> 	;		to return from system call -for IRET-.
  2343                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2344                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2345                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2346                              <1> 	;
  2347                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2348                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2349                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2350                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2351                              <1> 	;	compatibles was using 1MB segmented memory 
  2352                              <1> 	;	in 8086/8088 times.
  2353                              <1> 	;
  2354                              <1> 	; INPUTS ->
  2355                              <1> 	;    r1 - process number of process to be read in
  2356                              <1> 	;    p.break - negative of word count of process 
  2357                              <1> 	;    p.dska - disk address of the process		
  2358                              <1> 	;    u.emt - determines handling of emt's 	
  2359                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2360                              <1> 	; OUTPUTS ->
  2361                              <1> 	;    8 = (u.ilgins)
  2362                              <1> 	;    24 = (u.emt)
  2363                              <1> 	;    swp - bit 10 is set to indicate read 
  2364                              <1> 	;		(bit 15=0 when reading is done)	
  2365                              <1> 	;    swp+2 - disk block address
  2366                              <1> 	;    swp+4 - negative word count 	
  2367                              <1> 	;      ((swp+6 - address of user structure)) 
  2368                              <1> 	;
  2369                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2370                              <1> 	;
  2371                              <1> 	; INPUTS ->
  2372                              <1> 	;    AL	- new process number (to be swapped in)	 
  2373                              <1> 	; OUTPUTS ->
  2374                              <1> 	;    none
  2375                              <1> 	;
  2376                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2377                              <1> 	;
  2378                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2379 00004F25 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2380 00004F27 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2381 00004F2C BF[F06E0000]        <1> 	mov	edi, user ; active user (u) structure	
  2382 00004F31 F3A5                <1> 	rep	movsd
  2383 00004F33 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2384 00004F34 8B3D[F46E0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2385                              <1> 			     ;      points to user registers)
  2386 00004F3A 8B0D[F06E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2387                              <1> 			     ; (for IRET)
  2388                              <1> 			     ; [u.sp] -> EIP (user)
  2389                              <1> 			     ; [u.sp+4]-> CS (user)
  2390                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2391                              <1> 			     ; [u.sp+12] -> ESP (user)
  2392                              <1> 			     ; [u.sp+16] -> SS (user)		
  2393                              <1> 	; 28/08/2015
  2394 00004F40 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2395 00004F42 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2396                              <1> 			     ; (for IRET) 	
  2397 00004F45 C1E902              <1> 	shr	ecx, 2	       		
  2398 00004F48 F3A5                <1> 	rep	movsd
  2399 00004F4A 8B25[F46E0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2400 00004F50 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2401 00004F51 C3                  <1> 	retn
  2402                              <1> 
  2403                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2404                              <1> 	;rswap:
  2405                              <1>        		; asl r1 / process number x2 for index
  2406                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2407                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2408                              <1>        		; bis $2000,swp / read
  2409                              <1>        		; jsr r0,ppoke / read it in 
  2410                              <1> 	; 1:
  2411                              <1>        		; tstb swp+1 / done
  2412                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2413                              <1>        		; mov u.emt,*$30 / yes move these
  2414                              <1>        		; mov u.ilgins,*$10 / back
  2415                              <1>        		; rts r0 / return
  2416                              <1> 
  2417                              <1> 	;unpack: ; / move stack back to its normal place
  2418                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2419                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2420                              <1> 		; blos 2f / yes, return
  2421                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2422                              <1> 			     ; / before swapping
  2423                              <1> 		; bhis 2f / yes, return
  2424                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2425                              <1> 		; add r3,r2
  2426                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2427                              <1> 	; 1:
  2428                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2429                              <1> 		; cmp r2,u.break / in core
  2430                              <1> 		; bne 1b
  2431                              <1> 	; 2:
  2432                              <1>        		; rts r0
  2433                              <1> 
  2434                              <1> putlu: 
  2435                              <1> 	; 12/09/2015
  2436                              <1> 	; 02/09/2015
  2437                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2438                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2439                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2440                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2441                              <1> 	; the last process on the queue to process in r1 by putting
  2442                              <1> 	; the process number in r1 into the last process's link.
  2443                              <1> 	;
  2444                              <1> 	; INPUTS ->
  2445                              <1> 	;    r1 - user process number
  2446                              <1> 	;    r2 - points to lowest priority queue 
  2447                              <1> 	;    p.dska - disk address of the process		
  2448                              <1> 	;    u.emt - determines handling of emt's 	
  2449                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2450                              <1> 	; OUTPUTS ->
  2451                              <1> 	;    r3 - process number of last process on the queue upon
  2452                              <1> 	;	  entering putlu
  2453                              <1> 	;    p.link-1 + r3 - process number in r1
  2454                              <1> 	;    r2 - points to lowest priority queue
  2455                              <1> 	;
  2456                              <1> 	; ((Modified registers: EDX, EBX)) 
  2457                              <1> 	;
  2458                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2459                              <1> 
  2460                              <1> 	; eBX = r2
  2461                              <1> 	; eAX = r1 (AL=r1b)
  2462                              <1> 
  2463 00004F52 BB[EA6E0000]        <1> 	mov	ebx, runq
  2464 00004F57 0FB613              <1> 	movzx  	edx, byte [ebx]
  2465 00004F5A 43                  <1> 	inc	ebx
  2466 00004F5B 20D2                <1> 	and	dl, dl
  2467                              <1> 		; tstb (r2)+ / is queue empty?
  2468 00004F5D 740A                <1>        	jz	short putlu_1
  2469                              <1> 		; beq 1f / yes, branch
  2470 00004F5F 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2471                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2472                              <1> 			     ; / in r3
  2473 00004F61 8882[656C0000]      <1>        	mov	[edx+p.link-1], al
  2474                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2475                              <1> 			     ; / "last users" link
  2476 00004F67 EB03                <1> 	jmp	short putlu_2
  2477                              <1> 		; br 2f /
  2478                              <1> putlu_1: ; 1:
  2479 00004F69 8843FF              <1> 	mov	[ebx-1], al
  2480                              <1>        		; movb r1,-1(r2) / user is only user; 
  2481                              <1> 			    ; / put process no. at beginning and at end
  2482                              <1> putlu_2: ; 2: 
  2483 00004F6C 8803                <1> 	mov	[ebx], al
  2484                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2485                              <1> 			     ; / on the queue
  2486 00004F6E 88C2                <1> 	mov	dl, al
  2487 00004F70 88B2[656C0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2488                              <1> 		; dec r2 / restore r2
  2489 00004F76 C3                  <1>         retn
  2490                              <1> 		; rts r0
  2491                              <1> 
  2492                              <1> ;copyz:
  2493                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2494                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2495                              <1> ;       mov     (r0)+,r1
  2496                              <1> ;       mov     (r0)+,r2
  2497                              <1> ;1:
  2498                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2499                              <1> ;       cmp     r1,r2 
  2500                              <1> ;       blo     1b
  2501                              <1> ;       mov     (sp)+,r2 / restore r2
  2502                              <1> ;       mov     (sp)+,r1 / restore r1
  2503                              <1> ;       rts     r0 
  2504                              <1> 
  2505                              <1> idle:
  2506                              <1> 	; 01/09/2015
  2507                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2508                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2509                              <1> 	; (idle & wait loop)
  2510                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2511                              <1> 	; idle procedure!
  2512                              <1>       	;
  2513                              <1>   	; 01/09/2015
  2514 00004F77 FB                  <1> 	sti
  2515                              <1>       	; 29/07/2013
  2516 00004F78 F4                  <1>       	hlt
  2517 00004F79 90                  <1>       	nop ; 10/10/2013
  2518 00004F7A 90                  <1>       	nop
  2519 00004F7B 90                  <1>       	nop
  2520                              <1>       	; 23/10/2013
  2521 00004F7C 90                  <1>       	nop
  2522 00004F7D 90                  <1>       	nop
  2523 00004F7E 90                  <1>       	nop
  2524 00004F7F 90                  <1>       	nop
  2525 00004F80 C3                  <1>       	retn      
  2526                              <1> 
  2527                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2528                              <1> 	;clr *$ps / clear ps
  2529                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2530                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2531                              <1> 	;1 / wait for interrupt
  2532                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2533                              <1> 	;mov (sp)+,*$ps
  2534                              <1> 	;rts r0
  2535                              <1> 
  2536                              <1> clear:
  2537                              <1> 	; 03/02/2022
  2538                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2539                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2540                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2541                              <1> 	; on the current device (cdev)
  2542                              <1> 	;	
  2543                              <1> 	; INPUTS ->
  2544                              <1> 	;    r1 - block number of block to be zeroed
  2545                              <1> 	;    cdev - current device number 
  2546                              <1> 	; OUTPUTS ->
  2547                              <1> 	;    a zeroed I/O buffer onto the current device
  2548                              <1> 	;    r1 - points to last entry in the I/O buffer
  2549                              <1> 	;
  2550                              <1> 	; ((AX = R1)) input/output
  2551                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2552                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2553                              <1> 
  2554 00004F81 E8AF0D0000          <1> 	call 	wslot
  2555                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2556                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2557 00004F86 89DF                <1> 	mov	edi, ebx ; r5
  2558 00004F88 89C2                <1> 	mov	edx, eax
  2559 00004F8A B980000000          <1> 	mov	ecx, 128
  2560                              <1> 		; mov $256.,r3
  2561 00004F8F 31C0                <1> 	xor	eax, eax
  2562 00004F91 F3AB                <1> 	rep	stosd
  2563 00004F93 89D0                <1> 	mov	eax, edx
  2564                              <1> ; 1: 
  2565                              <1>        		; clr (r5)+ / zero data word in buffer
  2566                              <1>        		; dec r3
  2567                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2568                              <1> 	;call	dskwr
  2569                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2570                              <1>                              ; / block specified in r1
  2571                              <1> 	; eAX (r1) = block number
  2572                              <1> 	;retn
  2573                              <1> 		; rts r0
  2574                              <1> 	; 03/02/2022
  2575 00004F95 E9B70D0000          <1> 	jmp	dskwr
  1992                                  %include 'u4.s'        ; 15/04/2015
  1993                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  1994                              <1> ; Last Modification: 26/02/2022
  1995                              <1> ; ----------------------------------------------------------------------------
  1996                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1997                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1998                              <1> ;
  1999                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2000                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2001                              <1> ; <Bell Laboratories (17/3/1972)>
  2002                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2003                              <1> ;
  2004                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2005                              <1> ;
  2006                              <1> ; ****************************************************************************
  2007                              <1> ; 14/10/2015
  2008                              <1> 
  2009                              <1> ;setisp:
  2010                              <1>        ;mov     r1,-(sp)
  2011                              <1>        ;mov     r2,-(sp)
  2012                              <1>        ;mov     r3,-(sp)
  2013                              <1>        ;mov     clockp,-(sp)
  2014                              <1>        ;mov     $s.syst+2,clockp
  2015                              <1>        ;jmp     (r0)
  2016                              <1> 
  2017                              <1> clock: ; / interrupt from 60 cycle clock
  2018                              <1> 	
  2019                              <1> 	; 14/10/2015
  2020                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2021                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2022                              <1> 
  2023                              <1>        ;mov     r0,-(sp) / save r0
  2024                              <1>        ;tst     *$lks / restart clock?
  2025                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2026                              <1>        ;inc     (r0)
  2027                              <1>        ;bne     1f
  2028                              <1>        ;inc     -(r0)
  2029                              <1> ;1:
  2030                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2031                              <1>        ;inc     (r0)
  2032                              <1>        ;bne     1f
  2033                              <1>        ;inc     -(r0)
  2034                              <1> ;1:
  2035                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2036                              <1> 
  2037 00004F9A 803D[346F0000]00    <1> 	cmp	byte [u.quant], 0
  2038 00004FA1 772C                <1> 	ja	short clk_1
  2039                              <1> 	;
  2040 00004FA3 803D[EF6E0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2041 00004FAA 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2042 00004FAC 803D[416F0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2043 00004FB3 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2044 00004FB5 66833D[366F0000]00  <1> 	cmp	word [u.intr], 0
  2045 00004FBD 7616                <1> 	jna	short clk_2
  2046                              <1> clk_0:
  2047                              <1> 	; 14/10/2015
  2048 00004FBF FE05[EF6E0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2049 00004FC5 58                  <1> 	pop	eax ; return address to the timer interrupt
  2050                              <1> 	;
  2051 00004FC6 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2052                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2053 00004FC8 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2054                              <1> 	;
  2055 00004FCA E9D0EBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2056                              <1> clk_1:
  2057 00004FCF FE0D[346F0000]      <1> 	dec	byte [u.quant]
  2058                              <1> clk_2:
  2059 00004FD5 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2060                              <1> 
  2061                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2062                              <1> 
  2063                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2064                              <1>        ;decb    (r0)
  2065                              <1>        ;bge     1f / if less than 0
  2066                              <1>        ;clrb    (r0) / make it 0
  2067                              <1> ;1: / decrement time out counts return now if priority was not 0
  2068                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2069                              <1>        ;bge     2f / yes, check time outs
  2070                              <1>        ;tstb    (r0) / no, user timed out?
  2071                              <1>        ;bne     1f / no
  2072                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2073                              <1>        ;bne     1f / no, 1f
  2074                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2075                              <1>        ;sys     0 / sysrele
  2076                              <1>        ;rti
  2077                              <1> ;2: / priority is high so just decrement time out counts
  2078                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2079                              <1> ;2:
  2080                              <1>        ;tstb    (r0) / is the time out?
  2081                              <1>        ;beq     3f / yes, 3f (get next entry)
  2082                              <1>        ;decb    (r0) / no, decrement the time
  2083                              <1>        ;bne     3f / isit zero now?
  2084                              <1>        ;incb    (r0) / yes, increment the time
  2085                              <1> ;3:
  2086                              <1>        ;inc     r0 / next entry
  2087                              <1>        ;cmp     r0,$touts / end of toutt table?
  2088                              <1>        ;blo     2b / no, check this entry
  2089                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2090                              <1>        ;rti / return from interrupt
  2091                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2092                              <1>        ;mov     (sp)+,r0 / restore r0
  2093                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2094                              <1>        ;jsr     r0,setisp / save registers
  2095                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2096                              <1>                                ;  / the table
  2097                              <1> ;1:
  2098                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2099                              <1>        ;beq     2f / yes
  2100                              <1>        ;decb    toutt(r0) / no, decrement the time
  2101                              <1>        ;bne     2f / is the time 0, now
  2102                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2103                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2104                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2105                              <1> ;2:
  2106                              <1>        ;dec     r0 / set up r0 for next entry
  2107                              <1>        ;bge     1b / finished? , no, go back
  2108                              <1>        ;br      retisp / yes, restore registers and do a rti
  2109                              <1> 
  2110                              <1> ;retisp:
  2111                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2112                              <1>        ;mov     (sp)+,r3
  2113                              <1>        ;mov     (sp)+,r2
  2114                              <1>        ;mov     (sp)+,r1
  2115                              <1>        ;mov     (sp)+,r0
  2116                              <1>        ;rti     / return from interrupt
  2117                              <1> 
  2118                              <1> 
  2119                              <1> wakeup: ; / wakeup processes waiting for an event 
  2120                              <1> 	; / by linking them to the queue
  2121                              <1> 	;
  2122                              <1> 	; 26/02/2022
  2123                              <1> 	; 15/09/2015
  2124                              <1> 	; 29/06/2015
  2125                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2126                              <1> 	;
  2127                              <1> 	; 15/05/2013 - 02/06/2014
  2128                              <1> 	; Retro UNIX 8086 v1 modification !
  2129                              <1> 	; (Process/task switching routine by using
  2130                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2131                              <1> 	;
  2132                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2133                              <1> 	; sleeping in the specified wait channel by creating a link 
  2134                              <1> 	; to it from the last user process on the run queue.
  2135                              <1> 	; If there is no process to wake up, nothing happens.
  2136                              <1> 	;
  2137                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2138                              <1> 	; 'switching' status of the current process (owns current tty)
  2139                              <1> 	; (via alt + function keys) to a process which has highest
  2140                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2141                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2142                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2143                              <1> 	; tty for tty switching by keyboard.)	 
  2144                              <1> 	; 
  2145                              <1> 	; INPUT -> 
  2146                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2147                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2148                              <1> 	;
  2149                              <1> 	; ((modified registers: EAX, EBX))
  2150                              <1> 	;
  2151 00004FD6 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2152 00004FD9 81C3[A86B0000]      <1> 	add	ebx, wlist
  2153 00004FDF 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2154 00004FE1 20C0                <1> 	and	al, al
  2155 00004FE3 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2156                              <1> 	;
  2157 00004FE5 30E4                <1> 	xor	ah, ah
  2158 00004FE7 8825[346F0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2159 00004FED 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2160                              <1> 	; 15/09/2015
  2161 00004FEF 0FB6D8              <1> 	movzx	ebx, al
  2162                              <1> 	; 26/02/2022 (p.waitc is not used)
  2163                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2164 00004FF2 FEC4                <1> 	inc	ah
  2165 00004FF4 88A3[756C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2166                              <1> 	;
  2167 00004FFA 57                  <1> 	push	edi
  2168 00004FFB 52                  <1> 	push	edx
  2169 00004FFC E851FFFFFF          <1> 	call	putlu
  2170 00005001 5A                  <1> 	pop	edx
  2171 00005002 5F                  <1> 	pop	edi
  2172                              <1> wa0:
  2173 00005003 C3                  <1> 	retn
  2174                              <1> 
  2175                              <1> sleep: 
  2176                              <1> 	; 26/02/2022
  2177                              <1> 	; 03/02/2022
  2178                              <1> 	; 15/09/2015
  2179                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2180                              <1> 	;
  2181                              <1> 	; 09/05/2013 - 20/03/2014
  2182                              <1> 	;
  2183                              <1> 	; Retro UNIX 8086 v1 modification !
  2184                              <1> 	; (Process/task switching and quit routine by using
  2185                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2186                              <1> 	;
  2187                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2188                              <1> 	; tty and tape output or input becomes available
  2189                              <1> 	; and process is put on waiting channel and swapped out,
  2190                              <1> 	; then -when the tty or tape is ready to write or read-
  2191                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2192                              <1> 	;
  2193                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2194                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2195                              <1> 	; status of the current process also INT 1Ch will count down
  2196                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2197                              <1> 	; to tty buffer of the current process and kernel will get
  2198                              <1> 	; user input by using tty buffer of the current process
  2199                              <1> 	; (instead of standard INT 16h interrupt).
  2200                              <1> 	; TTY output will be redirected to related video page of text mode
  2201                              <1> 	; (INT 10h will be called with different video page depending
  2202                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2203                              <1> 	; pseudo screens.)
  2204                              <1> 	;
  2205                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2206                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2207                              <1> 	; characters/data on serial port(s).
  2208                              <1> 	;
  2209                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2210                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2211                              <1> 	; 
  2212                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2213                              <1> 	;
  2214                              <1> 	;; 05/10/2013
  2215                              <1>         ;10/12/2013
  2216                              <1> 	;cmp   byte [u.uno], 1
  2217                              <1>         ;ja    short sleep0
  2218                              <1> 	;retn
  2219                              <1> 
  2220                              <1> 	; 20/03/2014
  2221                              <1> 	;mov	bx, [runq]
  2222                              <1> 	;cmp	bl, bh
  2223                              <1> 	;jne	short sleep0	
  2224                              <1> 	; 25/02/2014
  2225                              <1> 	;cmp word ptr [runq], 0
  2226                              <1> 	;ja short sleep0	
  2227                              <1> 	;retn
  2228                              <1> sleep0:
  2229                              <1> 	;
  2230 00005004 E849000000          <1> 	call	isintr
  2231                              <1> 	;jnz	sysret
  2232                              <1> 		; / wait for event
  2233                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2234                              <1> 			      ; / or quit from user
  2235                              <1>                		; br 2f / something happened
  2236                              <1> 			      ; / yes, his interrupt so return
  2237                              <1>                      	      ;	/ to user
  2238                              <1> 	; 03/02/2022
  2239 00005009 7405                <1> 	jz	short sleep_2
  2240                              <1> sleep_3:
  2241 0000500B E933EBFFFF          <1> 	jmp	sysret
  2242                              <1> sleep_2:
  2243                              <1> 	; 30/06/2015
  2244 00005010 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2245 00005013 81C3[A86B0000]      <1> 	add	ebx, wlist
  2246 00005019 8A03                <1> 	mov	al, [ebx]
  2247 0000501B 20C0                <1> 	and	al, al
  2248 0000501D 7407                <1> 	jz	short sleep1
  2249 0000501F 53                  <1> 	push	ebx
  2250 00005020 E82DFFFFFF          <1> 	call	putlu
  2251 00005025 5B                  <1> 	pop	ebx
  2252                              <1> sleep1:
  2253 00005026 A0[416F0000]        <1> 	mov	al, [u.uno]    
  2254 0000502B 8803                <1>   	mov	[ebx], al 	; put the process number
  2255                              <1> 				; in the wait channel
  2256                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2257                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2258                              <1> 				     ; / on the stack
  2259                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2260                              <1> 				     ; / to put to sleep in there
  2261                              <1>         ; 15/09/2015
  2262 0000502D 0FB6D8              <1> 	movzx	ebx, al
  2263 00005030 C683[756C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2264                              <1> 	; 26/02/2022 (p.waitc is not used)
  2265                              <1> 	;inc	ah
  2266                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2267                              <1> 	;
  2268 00005037 66FF35[DE6E0000]    <1> 	push    word [cdev]
  2269                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2270 0000503E E842FEFFFF          <1> 	call	swap
  2271                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2272 00005043 668F05[DE6E0000]    <1>         pop     word [cdev]
  2273                              <1> 		; mov (sp)+,cdev / restore device
  2274 0000504A E803000000          <1> 	call	isintr
  2275                              <1> 	; 22/09/2013
  2276                              <1> 	;jnz	sysret         
  2277                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2278                              <1>                		; br 2f / yes, return to new user
  2279                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2280                              <1> 				; / originally on the wait channel
  2281                              <1>        		; beq 1f / if 0 branch
  2282                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2283                              <1>        		; mov $300,*$ps / processor priority = 6
  2284                              <1> 		; jsr r0,putlu / create link to old process number
  2285                              <1>        		; clr *$ps / clear the status; process priority = 0
  2286                              <1> 	; 03/02/2022
  2287 0000504F 75BA                <1> 	jnz	short sleep_3
  2288                              <1>      ;1:
  2289 00005051 C3                  <1> 	retn
  2290                              <1> 		; rts r0 / return
  2291                              <1>      ;2:
  2292                              <1>         ;;jmp	sysret
  2293                              <1> 		; jmp sysret / return to user
  2294                              <1> 
  2295                              <1> isintr:
  2296                              <1> 	; 03/02/2022
  2297                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2298                              <1> 	;
  2299                              <1> 	; 09/05/2013 - 30/05/2014
  2300                              <1> 	;
  2301                              <1> 	; Retro UNIX 8086 v1 modification !
  2302                              <1> 	; (Process/task switching and quit routine by using
  2303                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2304                              <1> 	;
  2305                              <1> 	; Retro UNIX 8086 v1 modification:
  2306                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2307                              <1> 	;  and there is a 'quit' request by user;
  2308                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2309                              <1> 	;  "nothing to do". (20/10/2013)
  2310                              <1> 	;
  2311                              <1> 	; 20/10/2013
  2312 00005052 66833D[286F0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2313 0000505A 761F                <1> 	jna	short isintr2 ; retn
  2314                              <1> 	; 03/09/2013
  2315                              <1> 	; (nothing to do)
  2316                              <1> 	;retn
  2317                              <1> 	; 22/09/2013
  2318 0000505C 66833D[366F0000]00  <1> 	cmp	word [u.intr], 0
  2319 00005064 7615                <1> 	jna	short isintr2 ; retn
  2320                              <1> 	; 30/05/2014
  2321                              <1> 	;push	ax
  2322                              <1> 	; 03/02/2022
  2323 00005066 50                  <1> 	push	eax
  2324 00005067 66A1[386F0000]      <1> 	mov	ax, [u.quit]
  2325 0000506D 6609C0              <1> 	or	ax, ax ; 0 ?
  2326 00005070 7408                <1> 	jz	short isintr1 ; zf = 1
  2327 00005072 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2328 00005076 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2329                              <1> 	;xor	ax, ax ; zf = 1
  2330                              <1> 	; 03/02/2022
  2331 00005078 31C0                <1> 	xor	eax, eax ; zf = 1
  2332                              <1> isintr1:
  2333                              <1> 	;pop	ax
  2334                              <1> 	; 03/02/2022
  2335 0000507A 58                  <1> 	pop	eax
  2336                              <1> isintr2: ; 22/09/2013
  2337                              <1> 	; zf=1 -> nothing to do
  2338 0000507B C3                  <1> 	retn
  2339                              <1> 
  2340                              <1> 	; UNIX v1 original 'isintr' routine... 
  2341                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2342                              <1>        	;mov     r2,-(sp) / save r2
  2343                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2344                              <1>         ;                 / typewriter
  2345                              <1>        	;beq     1f / if 0, do nothing except skip return
  2346                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2347                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2348                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2349                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2350                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2351                              <1>         ;              / of interrupts
  2352                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2353                              <1>      ;1:
  2354                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2355                              <1>      ;4:
  2356                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2357                              <1>        	;mov     (sp)+,r1
  2358                              <1>        	;rts     r0
  2359                              <1>      ;3: / interrupt char = quit (fs)
  2360                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2361                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2362                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2363                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2364                              <1>      ;1: / find process control tty entry in tty block
  2365                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2366                              <1>        	;beq     1f / block found go to 1f
  2367                              <1>        	;add     $8,r1 / look at next tty block
  2368                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2369                              <1>        	;blo     1b / no
  2370                              <1>        	;br      4b / no process control tty found so go to 4b
  2371                              <1>      ;1:
  2372                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2373                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2374                              <1>         ;                  / identifier
  2375                              <1>        	;inc     0f / increment
  2376                              <1>      ;1:
  2377                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2378                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2379                              <1>         ;             / being typed out after you hit the interrupt
  2380                              <1>         ;             / key
  2381                              <1>        	;br      1b
  1993                                  %include 'u5.s'        ; 03/06/2015
  1994                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  1995                              <1> ; Last Modification: 12/02/2022
  1996                              <1> ; ----------------------------------------------------------------------------
  1997                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1998                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1999                              <1> ;
  2000                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2001                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2002                              <1> ; <Bell Laboratories (17/3/1972)>
  2003                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2004                              <1> ;
  2005                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2006                              <1> ;
  2007                              <1> ; ****************************************************************************
  2008                              <1> ; 14/11/2015
  2009                              <1> 
  2010                              <1> mget:
  2011                              <1> 	; 03/02/2022
  2012                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2013                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2014                              <1> 	;
  2015                              <1> 	; Get existing or (allocate) a new disk block for file
  2016                              <1> 	; 
  2017                              <1> 	; INPUTS ->
  2018                              <1> 	;    u.fofp (file offset pointer)
  2019                              <1> 	;    inode 
  2020                              <1> 	;    u.off (file offset)
  2021                              <1> 	; OUTPUTS ->
  2022                              <1> 	;    r1 (physical block number)
  2023                              <1> 	;    r2, r3, r5 (internal)
  2024                              <1> 	;
  2025                              <1> 	; ((AX = R1)) output
  2026                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2027                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2028                              <1> 
  2029                              <1> 		; mov *u.fofp,mq / file offset in mq
  2030                              <1> 		; clr ac / later to be high sig
  2031                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2032                              <1> 		; mov mq,r2
  2033                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2034                              <1> 		; bne 4f / branch for large file
  2035                              <1> mget_0:	
  2036                              <1> 	; 03/02/2022
  2037 0000507C 29C0                <1> 	sub	eax, eax
  2038 0000507E 29D2                <1> 	sub	edx, edx
  2039 00005080 29C9                <1> 	sub	ecx, ecx
  2040 00005082 29DB                <1> 	sub	ebx, ebx
  2041                              <1> 
  2042 00005084 8B35[086F0000]      <1>         mov     esi, [u.fofp]
  2043                              <1>         ;movzx	ebx, byte [esi+1]
  2044                              <1> 	; 03/02/2022
  2045 0000508A 46                  <1> 	inc	esi
  2046 0000508B 8A1E                <1> 	mov	bl, [esi]
  2047                              <1> 
  2048                              <1> 	; BX = r2
  2049                              <1> 	; 03/02/2022
  2050 0000508D F605[F76B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2051                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2052                              <1> 			  	     ; is this a large or small file
  2053 00005094 756A                <1> 	jnz 	short mget_5 ; 4f ; large file
  2054                              <1> 
  2055 00005096 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2056                              <1> 		; bit $!17,r2
  2057 00005099 7525                <1> 	jnz 	short mget_2
  2058                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2059 0000509B 80E30E              <1>         and     bl, 0Eh  
  2060                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2061                              <1> 	; 03/02/2022
  2062 0000509E 668B83[FC6B0000]    <1> 	mov	ax, [ebx+i.dskp]
  2063                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2064                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2065                              <1> 	; 03/02/2022
  2066 000050A5 09C0                <1> 	or	eax, eax
  2067                              <1> 	;or 	ax, ax
  2068 000050A7 7516                <1> 	jnz 	short mget_1 
  2069                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2070                              <1> 		       ; / for file
  2071 000050A9 E8A4000000          <1> 	call 	alloc
  2072                              <1> 		; jsr r0,alloc / allocate a new block
  2073                              <1>          ; eAX (r1) = Physical block number
  2074 000050AE 668983[FC6B0000]    <1> 	mov 	[ebx+i.dskp], ax
  2075                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2076 000050B5 E833020000          <1> 	call 	setimod	
  2077                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2078 000050BA E8C2FEFFFF          <1> 	call	clear
  2079                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2080                              <1> mget_1: ; 2:
  2081                              <1>         ; eAX (r1) = Physical block number
  2082 000050BF C3                  <1> 	retn 
  2083                              <1> 		; rts r0
  2084                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2085 000050C0 E88D000000          <1> 	call 	alloc
  2086                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2087                              <1> 	                     ; / block number in r1
  2088                              <1>         ; eAX (r1) = Physical block number
  2089 000050C5 E86B0C0000          <1> 	call 	wslot
  2090                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2091                              <1> 			     ; / first data word in buffer
  2092                              <1>         ; 03/02/2022
  2093 000050CA 31C9                <1> 	xor	ecx, ecx
  2094 000050CC B108                <1> 	mov	cl, 8
  2095                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2096                              <1> 		   ; into new indirect block area for the new
  2097                              <1> 		   ; large file		
  2098 000050CE 89DF                <1> 	mov 	edi, ebx ; r5
  2099 000050D0 BE[FC6B0000]        <1> 	mov 	esi, i.dskp 
  2100                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2101                              <1> 			   ; / block pointers
  2102                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2103                              <1> 			  ; / large file
  2104                              <1> 	;xor 	ax, ax ; mov ax, 0
  2105                              <1> 	; 03/02/2022
  2106 000050D5 31C0                <1> 	xor	eax, eax
  2107                              <1> mget_3: ;1:
  2108 000050D7 66A5                <1> 	movsw
  2109                              <1> 		; mov (r2),(r5)+
  2110 000050D9 668946FE            <1> 	mov 	[esi-2], ax
  2111                              <1> 		; clr (r2)+
  2112 000050DD E2F8                <1> 	loop	mget_3 ; 1b
  2113                              <1> 		; dec r3
  2114                              <1> 		; bgt 1b
  2115                              <1> 
  2116 000050DF B1F8                <1> 	mov 	cl, 256-8
  2117                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2118                              <1> mget_4:	; 1
  2119 000050E1 F366AB              <1> 	rep 	stosw
  2120                              <1> 		; clr (r5)+
  2121                              <1> 		; dec r3
  2122                              <1> 		; bgt 1b
  2123                              <1> 	; 24/03/2013
  2124                              <1>         ; AX (r1) = Physical block number
  2125 000050E4 E8680C0000          <1> 	call	dskwr
  2126                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2127                              <1>         ; eAX (r1) = Physical block number
  2128 000050E9 66A3[FC6B0000]      <1> 	mov 	[i.dskp], ax
  2129                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2130                              <1> 	; 03/02/2022
  2131 000050EF 800D[F76B0000]10    <1> 	or	byte [i.flgs+1], 10h
  2132                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2133                              <1> 		; bis $10000,i.flgs / set large file bit 
  2134                              <1> 				  ; / in i.flgs word of i-node
  2135 000050F6 E8F2010000          <1> 	call	setimod
  2136                              <1> 		; jsr r0,setimod / set i-node modified flag
  2137 000050FB E97CFFFFFF          <1>         jmp     mget_0 
  2138                              <1> 		; br mget
  2139                              <1> 
  2140                              <1> mget_5:  ; 4 ; large file
  2141                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2142                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2143                              <1> 			    ; / in indirect block
  2144                              <1> 		; mov r2,-(sp) / save on stack (*)
  2145                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2146                              <1>        		          ; / indirect block
  2147                              <1> 		; bic $!16,r2
  2148 00005100 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2149 00005103 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2150                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2151                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2152                              <1> 	; There is always 1 indirect block for this file system
  2153                              <1> 	; 03/02/2022
  2154 00005104 66A1[FC6B0000]      <1> 	mov	ax, [i.dskp]
  2155                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2156                              <1> 		; mov i.dskp(r2),r1
  2157                              <1> 	; 03/02/2022
  2158 0000510A 09C0                <1> 	or	eax, eax
  2159                              <1> 	;or 	ax, ax ; R1
  2160 0000510C 7515                <1> 	jnz 	short mget_6 ; 2f
  2161                              <1> 		; bne 2f / if no indirect block exists
  2162 0000510E E83F000000          <1> 	call 	alloc
  2163                              <1> 		; jsr r0,alloc / allocate a new block
  2164 00005113 66A3[FC6B0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2165                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2166 00005119 E8CF010000          <1> 	call 	setimod
  2167                              <1> 		; jsr r0,setimod / set i-node modified byte
  2168                              <1> 	; eAX = new block number
  2169 0000511E E85EFEFFFF          <1> 	call 	clear
  2170                              <1> 		; jsr r0,clear / clear new block
  2171                              <1> mget_6: ;2
  2172                              <1> 	; 05/03/2013
  2173                              <1> 	; eAX = r1, physical block number (of indirect block)
  2174 00005123 E89B0B0000          <1> 	call 	dskrd ; read indirect block
  2175                              <1> 		; jsr r0,dskrd / read in indirect block
  2176 00005128 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2177                              <1> 		; mov (sp)+,r2 / get offset
  2178                              <1> 	; eAX = r1, physical block number (of indirect block)
  2179 00005129 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2180                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2181                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2182 0000512A 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2183                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2184                              <1> 	                  ; / points to location of inter
  2185                              <1> 	; 03/02/2022
  2186 0000512C 668B03              <1> 	mov	ax, [ebx]
  2187                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2188                              <1> 			      ; in file sought in R1 (AX)
  2189                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2190                              <1> 	               	    ; / sought in r1
  2191                              <1> 	; 03/02/2022
  2192 0000512F 09C0                <1> 	or	eax, eax
  2193                              <1> 	;or 	ax, ax
  2194 00005131 751D                <1>         jnz 	short mget_7 ; 2f
  2195                              <1> 		; bne 2f / if no block exists 
  2196 00005133 E81A000000          <1> 	call 	alloc
  2197                              <1> 		; jsr r0,alloc / allocate a new block
  2198 00005138 668903              <1> 	mov 	[ebx], ax ; R1
  2199                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2200                              <1> 	                    ; / indirect block
  2201 0000513B 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2202                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2203 0000513C 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2204 0000513D 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2205 0000513E 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2206                              <1> 		; mov (r2),-(sp) / save block number of new block
  2207                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2208 00005140 E8F00B0000          <1> 	call 	wslot
  2209                              <1> 		; jsr r0,wslot
  2210                              <1>         ; eAX (r1) = physical block number
  2211                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2212 00005145 E8070C0000          <1> 	call 	dskwr
  2213                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2214                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2215                              <1> 			     ; / back out on disk
  2216 0000514A 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2217                              <1> 		; mov (sp),r1 / restore block number of new block	
  2218                              <1> 	; eAX (r1) = physical block number of new block
  2219 0000514B E831FEFFFF          <1> 	call 	clear
  2220                              <1> 		; jsr r0,clear / clear new block	
  2221                              <1> mget_7: ; 2
  2222 00005150 5A                  <1> 	pop 	edx ; **
  2223                              <1> 		; tst (sp)+ / bump stack pointer
  2224                              <1> 	; eAX (r1) = Block number of new block
  2225 00005151 C3                  <1> 	retn
  2226                              <1> 		; rts r0
  2227                              <1> 
  2228                              <1> alloc:
  2229                              <1> 	; 03/02/2022
  2230                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2231                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2232                              <1> 	;
  2233                              <1> 	; get a free block and 
  2234                              <1> 	; set the corresponding bit in the free storage map
  2235                              <1> 	; 
  2236                              <1> 	; INPUTS ->
  2237                              <1> 	;    cdev (current device)
  2238                              <1> 	;    r2 
  2239                              <1> 	;    r3
  2240                              <1> 	; OUTPUTS ->
  2241                              <1> 	;    r1 (physical block number of block assigned)
  2242                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2243                              <1> 	;
  2244                              <1> 	; ((AX = R1)) output
  2245                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2246                              <1>         ;    ((Modified registers: DX, CX))  
  2247                              <1> 
  2248                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2249                              <1> 		;mov r3,-(sp)
  2250                              <1> 	;push 	ecx
  2251 00005152 53                  <1> 	push 	ebx ; R2
  2252                              <1> 	;push 	edx ; R3
  2253 00005153 BB[B07B0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2254                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2255 00005158 803D[DE6E0000]00    <1> 	cmp 	byte [cdev], 0
  2256                              <1> 		; tst cdev
  2257 0000515F 7605                <1> 	jna	short alloc_1
  2258                              <1> 		; beq 1f / drum is device
  2259 00005161 BB[B87D0000]        <1> 	mov	ebx, mount
  2260                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2261                              <1> 			      ; / free storage map
  2262                              <1> alloc_1: ; 1
  2263                              <1> 	; 03/02/2022
  2264                              <1> 	;sub	ecx, ecx
  2265                              <1> 	;sub	edx, edx
  2266                              <1> 	;sub	eax, eax
  2267                              <1> 
  2268 00005166 668B0B              <1>         mov	cx, [ebx]
  2269                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2270                              <1> 			     ; / storage map
  2271                              <1> 	; 03/02/2022
  2272 00005169 C1E103              <1> 	shl	ecx, 3
  2273                              <1> 	;shl	cx, 3
  2274                              <1> 		; asl r1 / multiply r1 by eight gives 
  2275                              <1> 		; number of blocks in device
  2276                              <1> 		; asl r1
  2277                              <1> 		; asl r1
  2278                              <1> 	;;push	cx ;; 01/08/2013
  2279                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2280 0000516C 31C0                <1> 	xor 	eax, eax ; 0
  2281                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2282                              <1> alloc_2: ; 1
  2283 0000516E 43                  <1> 	inc 	ebx ; 18/8/2012
  2284 0000516F 43                  <1> 	inc 	ebx ; 
  2285 00005170 668B13              <1> 	mov 	dx, [ebx]
  2286                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2287                              <1> 	; 03/02/2022
  2288 00005173 09D2                <1> 	or	edx, edx
  2289                              <1> 	;or 	dx, dx
  2290 00005175 750D                <1> 	jnz 	short alloc_3 ; 1f
  2291                              <1> 		; bne 1f / branch if any free blocks in this word	
  2292 00005177 6683C010            <1> 	add 	ax, 16
  2293                              <1> 		; add $16.,r1
  2294                              <1> 	; 03/02/2022
  2295 0000517B 39C8                <1> 	cmp	eax, ecx
  2296                              <1> 	;cmp 	ax, cx    
  2297                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2298 0000517D 72EF                <1> 	jb 	short alloc_2
  2299                              <1> 		; blo 1b
  2300                              <1> 	; 14/11/2015
  2301                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2302                              <1> 	;	because of a (DMA or another) r/w error, 
  2303                              <1> 	;	we will be here, at 'jmp panic' code address,
  2304                              <1> 	;	even if the (disk) file system space is not full !!!
  2305                              <1> 	;	(cx = 0)	
  2306                              <1> 	;
  2307 0000517F E94DE2FFFF          <1> 	jmp     panic 
  2308                              <1> 		; jmp panic / found no free storage
  2309                              <1> alloc_3: ; 1
  2310                              <1> 	; 03/02/2022
  2311 00005184 D1EA                <1> 	shr	edx, 1
  2312                              <1> 	;shr	dx, 1
  2313                              <1> 		; asr r3 / find a free block
  2314 00005186 7203                <1> 	jc	short alloc_4 ; 1f
  2315                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2316                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2317                              <1> 	; 03/02/2022
  2318 00005188 40                  <1> 	inc	eax
  2319                              <1> 	;inc	ax
  2320                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2321 00005189 EBF9                <1> 	jmp 	short alloc_3
  2322                              <1> 		; br 1b
  2323                              <1> alloc_4: ; 1:
  2324                              <1> 	;; pop cx ;; 01/08/2013
  2325                              <1> 		; tst (sp)+ / bump sp
  2326                              <1> 	; 02/04/2013 
  2327 0000518B E829000000          <1> 	call	free3
  2328                              <1> 		; jsr r0,3f / have found a free block
  2329                              <1> 	; 21/8/2012
  2330 00005190 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2331 00005193 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2332                              <1> 		; bic r3,(r2) / set bit for this block 
  2333                              <1> 		            ; / i.e. assign block
  2334                              <1> 		; br 2f
  2335 00005196 EB09                <1> 	jmp 	short alloc_5
  2336                              <1> 
  2337                              <1> free:
  2338                              <1> 	; 03/02/2022
  2339                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2340                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2341                              <1> 	;
  2342                              <1> 	; calculates byte address and bit position for given block number
  2343                              <1> 	; then sets the corresponding bit in the free storage map
  2344                              <1> 	; 
  2345                              <1> 	; INPUTS ->
  2346                              <1> 	;    r1 - block number for a block structured device
  2347                              <1> 	;    cdev - current device 
  2348                              <1> 	; OUTPUTS ->
  2349                              <1> 	;    free storage map is updated
  2350                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2351                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2352                              <1> 	;
  2353                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2354                              <1>         ;  ((Modified registers: DX, CX))  
  2355                              <1> 
  2356                              <1> 		;mov r2,-(sp) / save r2, r3
  2357                              <1> 		;mov r3,-(sp)
  2358                              <1> 	;push 	ecx
  2359 00005198 53                  <1> 	push 	ebx ; R2
  2360                              <1> 	;push 	edx ; R3 
  2361                              <1> 
  2362 00005199 E81B000000          <1>         call    free3
  2363                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2364                              <1> 				 ; / in free storage map for block
  2365 0000519E 660913              <1> 	or 	[ebx], dx  
  2366                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2367                              <1> 			    ;  / indicates free block	
  2368                              <1> 	; 0 -> allocated, 1 -> free
  2369                              <1> 
  2370                              <1> alloc_5:
  2371                              <1> 	; 07/04/2013
  2372                              <1> free_1: ; 2:
  2373                              <1> 	;pop 	edx
  2374                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2375 000051A1 5B                  <1> 	pop	ebx
  2376                              <1> 		; mov (sp)+,r2
  2377                              <1> 	; pop	ecx
  2378 000051A2 803D[DE6E0000]00    <1> 	cmp 	byte [cdev], 0
  2379                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2380                              <1> 			 ; / cdev = 1, mountable device
  2381 000051A9 7707                <1> 	ja	short alloc_6 ; 1f
  2382                              <1> 		; bne 1f
  2383                              <1> 	;mov	byte [smod], 1
  2384 000051AB FE05[ED6E0000]      <1> 	inc 	byte [smod]
  2385                              <1> 		; incb smod / set super block modified for drum
  2386                              <1> 	; eAX (r1) = block number
  2387 000051B1 C3                  <1> 	retn
  2388                              <1> 		; rts r0
  2389                              <1> free_2:
  2390                              <1> alloc_6: ; 1:
  2391                              <1> 	;mov 	byte [mmod], 1
  2392 000051B2 FE05[EE6E0000]      <1> 	inc 	byte [mmod]
  2393                              <1> 		; incb	mmod 
  2394                              <1> 		  ; / set super block modified for mountable device
  2395                              <1> 	; eAX (r1) = block number
  2396 000051B8 C3                  <1> 	retn	
  2397                              <1> 		; rts r0
  2398                              <1> free3:
  2399                              <1> 	; 03/02/2022
  2400                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2401                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2402                              <1> 	;
  2403                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2404                              <1> 	; 
  2405                              <1> alloc_free_3: ; 3
  2406                              <1> 	;mov 	dx, 1
  2407                              <1> 	; 03/02/2022
  2408 000051B9 31D2                <1> 	xor	edx, edx
  2409 000051BB 42                  <1> 	inc	edx
  2410                              <1> 	; edx = 1
  2411 000051BC 88C1                <1> 	mov 	cl, al
  2412                              <1> 		; mov r1,r2 / block number, k, = 1		
  2413 000051BE 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2414                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2415 000051C1 7402                <1> 	jz 	short free4
  2416                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2417                              <1> 			       ; / (k) mod 8
  2418                              <1> 	;shl 	dx, cl
  2419                              <1> 	; 03/02/2022
  2420 000051C3 D3E2                <1> 	shl	edx, cl
  2421                              <1> free4:
  2422 000051C5 0FB7D8              <1> 	movzx 	ebx, ax
  2423                              <1> 		; mov r1,r2 / divide block number by 16
  2424                              <1> 	; 03/02/2022
  2425 000051C8 C1EB04              <1> 	shr	ebx, 4
  2426                              <1> 	;shr 	bx, 4
  2427                              <1> 		; asr r2
  2428                              <1> 		; asr r2
  2429                              <1> 		; asr r2
  2430                              <1> 		; asr r2
  2431                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2432                              <1> 		       ; / bit for block is in lower half of word
  2433                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2434                              <1> 		        ; / storage map
  2435                              <1> alloc_free_4: ; 1
  2436                              <1> 	; 03/02/2022
  2437 000051CB D1E3                <1> 	shl	ebx, 1
  2438                              <1> 	;shl 	bx, 1
  2439                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2440 000051CD 81C3[B27B0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2441                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2442                              <1> 	    		        ; / with block bit in it 	
  2443 000051D3 803D[DE6E0000]00    <1> 	cmp	byte [cdev], 0
  2444                              <1> 		; tst cdev
  2445 000051DA 7606                <1> 	jna	short alloc_free_5
  2446                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2447 000051DC 81C308020000        <1> 	add	ebx, mount - systm
  2448                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2449                              <1> 				    ; / mountable device with bit of block to be
  2450                              <1> 				    ; / freed
  2451                              <1> alloc_free_5: ; 1 
  2452 000051E2 C3                  <1> 	retn
  2453                              <1> 		; rts r0 / return to 'free'
  2454                              <1> 	      ; 2
  2455                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2456                              <1> 	
  2457                              <1> iget:
  2458                              <1> 	; 03/02/2022
  2459                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2460                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2461                              <1> 	;
  2462                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2463                              <1> 	;
  2464                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2465                              <1> 	; 
  2466                              <1> 	; INPUTS ->
  2467                              <1> 	;    ii - current i-number, rootdir
  2468                              <1> 	;    cdev - new i-node device
  2469                              <1> 	;    idev - current i-node device
  2470                              <1> 	;    imod - current i-node modified flag
  2471                              <1> 	;    mnti - cross device file i-number
  2472                              <1> 	;    r1 - i-numbe rof new i-node
  2473                              <1> 	;    mntd - mountable device number		
  2474                              <1> 	; 	 
  2475                              <1> 	; OUTPUTS ->
  2476                              <1> 	;    cdev, idev, imod, ii, r1
  2477                              <1> 	;
  2478                              <1> 	; ((AX = R1)) input/output
  2479                              <1> 	;
  2480                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2481                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2482                              <1> 
  2483 000051E3 8A15[DE6E0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2484 000051E9 8A35[DC6E0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2485                              <1> 	;
  2486 000051EF 663B05[DA6E0000]    <1> 	cmp 	ax, [ii]
  2487                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2488 000051F6 7504                <1> 	jne 	short iget_1
  2489                              <1> 		; bne 1f
  2490 000051F8 38F2                <1> 	cmp	dl, dh
  2491                              <1> 		; cmp idev,cdev
  2492                              <1> 			  ; / is device number of i-node = current device
  2493 000051FA 7472                <1>         je      short iget_5
  2494                              <1> 		; beq 2f
  2495                              <1> iget_1: ; 1:
  2496 000051FC 30DB                <1> 	xor	bl, bl
  2497 000051FE 381D[EC6E0000]      <1> 	cmp	[imod], bl ; 0	
  2498                              <1> 		; tstb imod / has i-node of current file
  2499                              <1> 			  ; / been modified i.e., imod set
  2500 00005204 7629                <1> 	jna	short iget_2
  2501                              <1> 		; beq 1f
  2502 00005206 881D[EC6E0000]      <1> 	mov	[imod], bl ; 0
  2503                              <1> 		;  clrb	imod / if it has, 
  2504                              <1> 			   ; / we must write the new i-node out on disk
  2505                              <1> 	; 03/02/2022
  2506 0000520C 50                  <1> 	push	eax ; *
  2507                              <1> 	;push	ax
  2508                              <1> 		; mov r1,-(sp)
  2509                              <1> 	;mov	dl, [cdev]
  2510 0000520D 52                  <1> 	push	edx ; **
  2511                              <1> 	;push	dx
  2512                              <1> 		; mov cdev,-(sp)
  2513 0000520E 66A1[DA6E0000]      <1> 	mov	ax, [ii]
  2514                              <1> 		; mov ii,r1
  2515                              <1> 	;mov	dh, [idev]
  2516 00005214 8835[DE6E0000]      <1> 	mov	[cdev], dh
  2517                              <1> 		; mov idev,cdev
  2518 0000521A FEC3                <1> 	inc	bl ; 1
  2519                              <1> 	; 31/07/2013
  2520 0000521C 881D[746F0000]      <1> 	mov     [rw], bl ; 1 == write 
  2521                              <1> 	;;28/07/2013 rw -> u.rw
  2522                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2523 00005222 E848000000          <1> 	call	icalc
  2524                              <1> 		; jsr r0,icalc; 1
  2525                              <1> 	;pop	dx
  2526                              <1> 	; 03/02/2022
  2527 00005227 5A                  <1> 	pop	edx ; **
  2528 00005228 8815[DE6E0000]      <1> 	mov	[cdev], dl
  2529                              <1> 		; mov (sp)+,cdev
  2530                              <1> 	; 03/02/2022
  2531 0000522E 58                  <1> 	pop	eax ; *
  2532                              <1> 	;pop	ax
  2533                              <1> 		; mov (sp)+,r1
  2534                              <1> iget_2: ; 1:
  2535 0000522F 6621C0              <1> 	and	ax, ax
  2536                              <1> 		; tst r1 / is new i-number non zero
  2537 00005232 7434                <1> 	jz	short iget_4 ; 2f
  2538                              <1> 		; beq 2f / branch if r1=0
  2539                              <1> 
  2540                              <1> 	;mov 	dl, [cdev]
  2541 00005234 08D2                <1> 	or	dl, dl
  2542                              <1> 		; tst cdev / is the current device number non zero
  2543                              <1> 			 ; / (i.e., device =/ drum)
  2544 00005236 7517                <1> 	jnz	short iget_3 ;  1f
  2545                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2546 00005238 663B05[E46E0000]    <1> 	cmp	ax, [mnti]			
  2547                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2548                              <1> 			    ; / file (root directory of mounted device)
  2549 0000523F 750E                <1> 	jne	short iget_3 ; 1f
  2550                              <1> 		; bne 1f
  2551                              <1>         ;mov    bl, [mntd]
  2552 00005241 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2553 00005243 8815[DE6E0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2554                              <1> 		; mov mntd,cdev / make mounted device the current device
  2555 00005249 66A1[E86E0000]      <1> 	mov	ax, [rootdir]
  2556                              <1> 		; mov rootdir,r1
  2557                              <1> iget_3: ; 1:
  2558 0000524F 66A3[DA6E0000]      <1> 	mov	[ii], ax
  2559                              <1> 		; mov r1,ii
  2560 00005255 8815[DC6E0000]      <1> 	mov	[idev], dl ; cdev
  2561                              <1> 		; mov cdev,idev
  2562 0000525B 30DB                <1> 	xor	bl, bl
  2563                              <1>         ; 31/07/2013
  2564 0000525D 881D[746F0000]      <1> 	mov     [rw], bl ; 0 == read 
  2565                              <1> 	;;28/07/2013 rw -> u.rw       
  2566                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2567 00005263 E807000000          <1> 	call	icalc
  2568                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2569                              <1> iget_4: ; 2:
  2570 00005268 66A1[DA6E0000]      <1> 	mov	ax, [ii]
  2571                              <1> 		; mov ii,r1
  2572                              <1> iget_5:
  2573 0000526E C3                  <1> 	retn
  2574                              <1> 		; rts r0
  2575                              <1> 
  2576                              <1> icalc:
  2577                              <1> 	; 03/02/2022
  2578                              <1> 	; 02/07/2015
  2579                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2580                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2581                              <1> 	;
  2582                              <1> 	; calculate physical block number from i-number then
  2583                              <1> 	; read or write that block
  2584                              <1> 	;
  2585                              <1> 	; 'icalc' is called from 'iget'
  2586                              <1> 	;
  2587                              <1> 	; for original unix v1:
  2588                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2589                              <1>        	; / (i+31.) mod 16. bytes from its start
  2590                              <1> 	;
  2591                              <1> 	; for retro unix 8086 v1:
  2592                              <1> 	;  i-node is located in block (i+47)/16 and
  2593                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2594                              <1> 	;
  2595                              <1> 	; INPUTS ->
  2596                              <1> 	;    r1 - i-number of i-node
  2597                              <1> 	; 	 
  2598                              <1> 	; OUTPUTS ->
  2599                              <1> 	;    inode r/w
  2600                              <1> 	;
  2601                              <1> 	; ((AX = R1)) input
  2602                              <1> 	;
  2603                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2604                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2605                              <1> 	;
  2606 0000526F 0FB7D0              <1> 	movzx	edx, ax	
  2607 00005272 6683C22F            <1> 	add	dx, 47
  2608 00005276 89D0                <1> 	mov	eax, edx
  2609                              <1> 	;add	ax, 47	; add 47 to inode number
  2610                              <1> 		; add $31.,r1 / add 31. to i-number
  2611 00005278 50                  <1> 	push	eax
  2612                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2613                              <1> 	; 03/02/2022
  2614 00005279 C1E804              <1> 	shr	eax, 4
  2615                              <1> 	;shr 	ax, 4
  2616                              <1> 		; asr r1 / divide by 16.
  2617                              <1> 		; asr r1
  2618                              <1> 		; asr r1
  2619                              <1> 		; asr r1 / r1 contains block number of block
  2620                              <1> 		       ; / in which i-node exists
  2621 0000527C E8420A0000          <1> 	call	dskrd
  2622                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2623                              <1> 	; 31/07/2013
  2624 00005281 803D[746F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2625                              <1> 	;; 28/07/2013 rw -> u.rw
  2626                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2627                              <1> 		; tst (r0)
  2628 00005288 7605                <1> 	jna	short icalc_1
  2629                              <1> 		; beq 1f / branch to wslot when argument
  2630                              <1> 		       ; / in icalc call = 1
  2631                              <1> 	; eAX = r1 = block number
  2632 0000528A E8A60A0000          <1> 	call	wslot
  2633                              <1> 		; jsr r0,wslot / set up data buffer for write
  2634                              <1> 			     ; / (will be same buffer as dskrd got)
  2635                              <1> 	; eBX = r5 points to first word in data area for this block
  2636                              <1> icalc_1: ; 1:
  2637 0000528F 5A                  <1> 	pop	edx 
  2638 00005290 83E20F              <1> 	and 	edx, 0Fh ; (i+47) mod 16
  2639                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2640                              <1> 			      ; / gives (i+31.) mod 16
  2641 00005293 C1E205              <1> 	shl 	edx, 5
  2642                              <1> 	; eDX = 32 * ((i+47) mod 16)
  2643 00005296 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2644 00005298 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2645                              <1>           	; eSI (r5) points to first word in i-node i.	
  2646                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2647                              <1> 			     ; / 32.*(i+31.)mod16
  2648                              <1> 		; mov $5,lsh / for i-node i.
  2649                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2650 0000529A BF[F66B0000]        <1> 	mov	edi, inode
  2651                              <1> 		; mov $inode,r1 / inode is address of first word 
  2652                              <1> 			      ; / of current i-node
  2653                              <1> 	; 03/02/2022
  2654 0000529F 29C9                <1> 	sub	ecx, ecx
  2655 000052A1 B108                <1> 	mov	cl, 8 
  2656                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2657                              <1> 		; mov $16.,r3
  2658                              <1>         ; 31/07/2013
  2659 000052A3 382D[746F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2660                              <1>        ;;28/07/2013 rw -> u.rw                 
  2661                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2662                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2663 000052A9 7609                <1> 	jna	short icalc_3
  2664                              <1> 		; beq 2f / r0 now contains proper return address 
  2665                              <1> 		       ; / for rts r0
  2666                              <1> icalc_2: ; 1:
  2667 000052AB 87F7                <1> 	xchg 	esi, edi
  2668                              <1> 	; overwrite old i-node (in buffer to be written)
  2669 000052AD F3A5                <1> 	rep 	movsd
  2670                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2671                              <1> 		; dec r3
  2672                              <1> 		; bgt 1b
  2673                              <1> 	;call	dskwr
  2674                              <1> 		; jsr r0,dskwr / write inode out on device
  2675                              <1> 	;retn
  2676                              <1> 		; rts r0
  2677                              <1> 	; 03/02/2022
  2678 000052AF E99D0A0000          <1> 	jmp	dskwr
  2679                              <1> icalc_3: ; 2:
  2680                              <1> 	; copy new i-node into inode area of (core) memory
  2681 000052B4 F3A5                <1> 	rep 	movsd
  2682                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2683                              <1> 		                ; / "inode" area of core
  2684                              <1> 		; dec r3
  2685                              <1> 		; bgt 2b
  2686 000052B6 C3                  <1> 	retn
  2687                              <1> 		; rts r0
  2688                              <1> 
  2689                              <1> access:
  2690                              <1> 	; 03/02/2022
  2691                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2692                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2693                              <1> 	;
  2694                              <1> 	; check whether user is owner of file or user has read or write
  2695                              <1> 	; permission (based on i.flgs).
  2696                              <1> 	;
  2697                              <1> 	; INPUTS ->
  2698                              <1> 	;    r1 - i-number of file
  2699                              <1> 	;    u.uid
  2700                              <1> 	; arg0 -> (owner flag mask)	 		
  2701                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2702                              <1> 	; OUTPUTS ->
  2703                              <1> 	;    inode (or jump to error)
  2704                              <1> 	;
  2705                              <1> 	; ((AX = R1)) input/output
  2706                              <1> 	;
  2707                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2708                              <1> 	;
  2709                              <1> 
  2710                              <1> 	;push	dx  ; save flags (DL)
  2711                              <1> 	; 03/02/2022
  2712 000052B7 52                  <1> 	push	edx ; save flags (DL)
  2713 000052B8 E826FFFFFF          <1> 	call	iget
  2714                              <1> 		; jsr r0,iget / read in i-node for current directory
  2715                              <1> 			    ; / (i-number passed in r1)
  2716 000052BD 8A0D[F66B0000]      <1> 	mov	cl, [i.flgs]
  2717                              <1> 		; mov i.flgs,r2
  2718                              <1> 	; 03/02/2022
  2719 000052C3 5A                  <1> 	pop	edx ; restore flags (DL)
  2720                              <1> 	;pop	dx  ; restore flags (DL)
  2721 000052C4 8A35[3E6F0000]      <1> 	mov	dh, [u.uid]
  2722 000052CA 3A35[F96B0000]      <1> 	cmp	dh, [i.uid]
  2723                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2724 000052D0 7503                <1> 	jne	short access_1
  2725                              <1> 		; bne 1f / no, then branch
  2726 000052D2 C0E902              <1> 	shr	cl, 2
  2727                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2728                              <1> 		        ; / read/write bits
  2729                              <1> 		; asrb r2
  2730                              <1> access_1: ; 1:
  2731 000052D5 20D1                <1> 	and	cl, dl
  2732                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2733                              <1> 			     ; / in access call
  2734 000052D7 7513                <1> 	jnz	short access_2
  2735                              <1> 		; bne 1f
  2736 000052D9 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2737                              <1> 		; tstb u.uid
  2738 000052DB 740F                <1> 	jz	short access_2 ; yes, super user
  2739                              <1> 	;jnz	error
  2740                              <1> 		; beq 1f
  2741                              <1> 		; jmp error
  2742 000052DD C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2742 000052E5 0000                <1>
  2743                              <1> 			; 'permission denied !' error
  2744 000052E7 E937E8FFFF          <1> 	jmp	error
  2745                              <1> 
  2746                              <1> access_2: ; 1:
  2747                              <1> 	; DL = flags
  2748 000052EC C3                  <1> 	retn
  2749                              <1> 		; rts r0
  2750                              <1> 
  2751                              <1> setimod:
  2752                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2753                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2754                              <1> 	;
  2755                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2756                              <1> 	; the inode has been modified. Also puts the time of modification
  2757                              <1> 	; into the inode.
  2758                              <1> 	;
  2759                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2760                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2761                              <1> 	;
  2762                              <1> 	
  2763                              <1> 	; push 	edx
  2764 000052ED 50                  <1> 	push	eax
  2765                              <1> 
  2766 000052EE C605[EC6E0000]01    <1> 	mov 	byte [imod], 1
  2767                              <1> 		; movb $1,imod / set current i-node modified bytes
  2768                              <1> 	; Erdogan Tan 14-7-2012
  2769 000052F5 E866E3FFFF          <1> 	call 	epoch
  2770                              <1> 		 ; mov s.time,i.mtim 
  2771                              <1> 			    ; / put present time into file modified time
  2772                              <1> 		 ; mov s.time+2,i.mtim+2
  2773                              <1> 
  2774 000052FA A3[106C0000]        <1> 	mov 	[i.mtim], eax
  2775                              <1> 	
  2776                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2777                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2778 000052FF 833D[0C6C0000]00    <1> 	cmp	dword [i.ctim], 0
  2779 00005306 7505                <1> 	jnz	short setimod_ok
  2780                              <1> 
  2781 00005308 A3[0C6C0000]        <1> 	mov 	[i.ctim], eax
  2782                              <1> 
  2783                              <1> setimod_ok: ; 31/07/2013
  2784 0000530D 58                  <1> 	pop	eax
  2785                              <1> 	;pop	edx
  2786                              <1> 	
  2787 0000530E C3                  <1> 	retn
  2788                              <1> 		; rts r0
  2789                              <1> 
  2790                              <1> itrunc:
  2791                              <1> 	; 03/02/2022
  2792                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2793                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2794                              <1> 	;
  2795                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2796                              <1> 	;  to zero length.
  2797                              <1> 	;
  2798                              <1> 	; INPUTS ->
  2799                              <1> 	;    r1 - i-number of i-node
  2800                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2801                              <1> 	;    i.flgs - large file flag		
  2802                              <1> 	;    i.size - size of file	
  2803                              <1> 	; 	 
  2804                              <1> 	; OUTPUTS ->
  2805                              <1> 	;    i.flgs - large file flag is cleared
  2806                              <1> 	;    i.size - set to 0	
  2807                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2808                              <1> 	;    setimod - set to indicate i-node has been modified
  2809                              <1> 	;    r1 - i-number of i-node  					
  2810                              <1> 	;
  2811                              <1> 	; ((AX = R1)) input/output
  2812                              <1> 	;
  2813                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2814                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2815                              <1> 
  2816 0000530F E8CFFEFFFF          <1> 	call	iget
  2817                              <1> 		; jsr r0,iget
  2818 00005314 BE[FC6B0000]        <1> 	mov	esi, i.dskp
  2819                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2820 00005319 31C0                <1> 	xor	eax, eax
  2821                              <1> itrunc_1: ; 1:
  2822 0000531B 66AD                <1> 	lodsw
  2823                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2824                              <1> 	; 03/02/2022
  2825 0000531D 09C0                <1> 	or	eax, eax
  2826                              <1> 	;or 	ax, ax
  2827 0000531F 7433                <1> 	jz	short itrunc_5
  2828                              <1> 		; beq 5f
  2829 00005321 56                  <1> 	push	esi
  2830                              <1> 		; mov r2,-(sp)
  2831                              <1> 	; 03/02/2022
  2832 00005322 F605[F76B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2833                              <1> 	;test	word [i.flgs], 1000h
  2834                              <1> 		; bit $10000,i.flgs / test large file bit?
  2835 00005329 7423                <1> 	jz	short itrunc_4
  2836                              <1> 		; beq 4f / if clear, branch
  2837 0000532B 50                  <1> 	push	eax
  2838                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2839 0000532C E892090000          <1> 	call	dskrd
  2840                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2841                              <1> 			     ; / pointed to by r5
  2842                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2843                              <1> 	; 03/02/2022
  2844 00005331 31C9                <1> 	xor	ecx, ecx
  2845 00005333 FEC5                <1> 	inc	ch ; mov ch, 1
  2846                              <1> 	; ecx = 256
  2847                              <1> 	;mov	ecx, 256
  2848                              <1> 		; mov $256.,r3 / move word count into r3
  2849 00005335 89DE                <1> 	mov	esi, ebx
  2850                              <1> itrunc_2: ; 2:
  2851 00005337 66AD                <1> 	lodsw
  2852                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2853                              <1> 			     ; / physical block number
  2854                              <1> 	; 03/02/2022
  2855 00005339 21C0                <1> 	and	eax, eax
  2856                              <1> 	;and	ax, ax
  2857 0000533B 7407                <1> 	jz	short itrunc_3
  2858                              <1> 		; beq 3f / branch if zero
  2859                              <1> 	; 03/02/2022
  2860 0000533D 51                  <1> 	push	ecx
  2861                              <1> 	;push	cx
  2862                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2863                              <1> 	;push	esi
  2864                              <1> 		; mov r5,-(sp)
  2865 0000533E E855FEFFFF          <1> 	call	free
  2866                              <1> 		; jsr r0,free / free block in free storage map
  2867                              <1> 	;pop	esi
  2868                              <1> 		; mov(sp)+,r5
  2869                              <1> 	;pop	cx
  2870 00005343 59                  <1> 	pop	ecx
  2871                              <1> 		; mov (sp)+,r3
  2872                              <1> itrunc_3: ; 3:
  2873 00005344 E2F1                <1> 	loop	itrunc_2
  2874                              <1> 		; dec r3 / decrement word count
  2875                              <1> 		; bgt 2b / branch if positive
  2876 00005346 58                  <1> 	pop	eax
  2877                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2878                              <1> 			     ; / indirect block
  2879                              <1> 	; 01/08/2013
  2880                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2881                              <1> 	; 03/02/2022
  2882 00005347 8025[F76B0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2883                              <1> itrunc_4: ; 4:
  2884 0000534E E845FEFFFF          <1> 	call	free
  2885                              <1> 		; jsr r0,free / free indirect block
  2886 00005353 5E                  <1> 	pop	esi
  2887                              <1> 		; mov (sp)+,r2
  2888                              <1> itrunc_5: ; 5:
  2889 00005354 81FE[0C6C0000]      <1> 	cmp	esi, i.dskp+16
  2890                              <1> 		; cmp r2,$i.dskp+16.
  2891 0000535A 72BF                <1> 	jb	short itrunc_1	
  2892                              <1> 		; bne 1b / branch until all i.dskp entries check
  2893                              <1> 	; 03/02/2022
  2894                              <1> 	;and	byte [i.flgs+1], 0EFh
  2895                              <1> 	; 01/08/2013
  2896                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2897                              <1> 		; bic $10000,i.flgs / clear large file bit
  2898 0000535C BF[FC6B0000]        <1> 	mov	edi, i.dskp
  2899                              <1> 	;mov	cx, 8
  2900                              <1> 	;xor 	ax, ax
  2901                              <1> 	; 03/02/2022
  2902 00005361 29C9                <1> 	sub	ecx, ecx
  2903 00005363 B108                <1> 	mov	cl, 8
  2904 00005365 29C0                <1> 	sub	eax, eax
  2905 00005367 66A3[FA6B0000]      <1> 	mov	[i.size], ax ; 0
  2906                              <1> 		; clr i.size / zero file size
  2907 0000536D F366AB              <1> 	rep	stosw
  2908                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2909                              <1> 			   ; / zero block pointers
  2910 00005370 E878FFFFFF          <1> 	call	setimod
  2911                              <1> 		; jsr r0,setimod / set i-node modified flag
  2912 00005375 66A1[DA6E0000]      <1> 	mov	ax, [ii]
  2913                              <1> 		; mov ii,r1
  2914 0000537B C3                  <1> 	retn
  2915                              <1> 		; rts r0
  2916                              <1> 
  2917                              <1> imap:
  2918                              <1> 	; 12/02/2022
  2919                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2920                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2921                              <1> 	;
  2922                              <1> 	; 'imap' finds the byte in core (superblock) containing
  2923                              <1> 	; allocation bit for an i-node whose number in r1.
  2924                              <1> 	;
  2925                              <1> 	; INPUTS ->
  2926                              <1> 	;    r1 - contains an i-number
  2927                              <1> 	;    fsp - start of table containing open files
  2928                              <1> 	;
  2929                              <1> 	; OUTPUTS ->
  2930                              <1> 	;    r2 - byte address of byte with the allocation bit
  2931                              <1> 	;    mq - a mask to locate the bit position.	
  2932                              <1> 	;	  (a 1 is in calculated bit posisiton)
  2933                              <1> 	;
  2934                              <1> 	; ((AX = R1)) input/output
  2935                              <1> 	; ((DL/DX = MQ)) output
  2936                              <1> 	; ((BX = R2)) output
  2937                              <1> 	;
  2938                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  2939                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  2940                              <1> 	;
  2941                              <1> 		; / get the byte that has the allocation bit for 
  2942                              <1> 		; / the i-number contained in r1
  2943                              <1> 	;mov	dx, 1
  2944 0000537C B201                <1> 	mov	dl, 1
  2945                              <1> 		; mov $1,mq / put 1 in the mq
  2946 0000537E 0FB7D8              <1> 	movzx	ebx, ax
  2947                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  2948                              <1>  		          ; / in the map we must find
  2949 00005381 6683EB29            <1> 	sub	bx, 41
  2950                              <1> 		; sub $41.,r2 / r2 has i-41
  2951 00005385 88D9                <1> 	mov	cl, bl
  2952                              <1> 		; mov r2,r3 / r3 has i-41
  2953 00005387 80E107              <1> 	and	cl, 7
  2954                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  2955                              <1> 			   ; / the bit position
  2956 0000538A 7402                <1> 	jz	short imap1
  2957                              <1> 	;shl	dx, cl
  2958 0000538C D2E2                <1> 	shl	dl, cl
  2959                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  2960                              <1> imap1:			   ; / to the left to mask the correct bit
  2961                              <1> 	; 03/02/2022
  2962 0000538E C1EB03              <1> 	shr	ebx, 3
  2963                              <1> 	;shr	bx, 3
  2964                              <1> 		; asr r2
  2965                              <1> 		; asr r2
  2966                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  2967                              <1> 		       ; / from the start of the map
  2968                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  2969 00005391 BE[B07B0000]        <1> 	mov	esi, systm
  2970                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  2971                              <1> 				; / the super block for drum
  2972                              <1> 	;cmp	word [cdev], 0
  2973 00005396 803D[DE6E0000]00    <1> 	cmp	byte [cdev], 0
  2974                              <1> 		; tst cdev / is the device the disk
  2975 0000539D 7606                <1> 	jna	short imap2
  2976                              <1> 		; beq 1f / yes
  2977 0000539F 81C608020000        <1> 	add	esi, mount - systm
  2978                              <1> 		; add $mount-systm,r2 / for mounted device,
  2979                              <1> 			; / r2 points to 1st word of its super block
  2980                              <1> imap2: ; 1:
  2981 000053A5 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  2982                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  2983 000053A8 6683C304            <1> 	add	bx, 4
  2984 000053AC 01F3                <1> 	add	ebx, esi
  2985                              <1>         	; add (sp)+,r2 / ?
  2986                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  2987                              <1> 		      ;; (2 + free map size + 2)
  2988                              <1> 		; add $2,r2 / ?
  2989                              <1>  	
  2990                              <1> 	; 12/02/2022
  2991 000053AE 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  2992 000053B4 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  2993                              <1> 			  ; if inode num overs inode count
  2994                              <1> 
  2995                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  2996                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  2997                              <1> 
  2998                              <1> 	; 11/02/2022
  2999                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3000                              <1> 	;	(number of requested inode > inode count)
  3001                              <1> 
  3002 000053B6 C3                  <1> 	retn
  3003                              <1> 		; rts r0
  1994                                  %include 'u6.s'        ; 31/05/2015
  1995                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  1996                              <1> ; Last Modification: 03/02/2022
  1997                              <1> ; ----------------------------------------------------------------------------
  1998                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1999                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2000                              <1> ;
  2001                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2002                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2003                              <1> ; <Bell Laboratories (17/3/1972)>
  2004                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2005                              <1> ;
  2006                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2007                              <1> ;
  2008                              <1> ; ****************************************************************************
  2009                              <1> ; 18/11/2015
  2010                              <1> 
  2011                              <1> readi:
  2012                              <1> 	; 03/02/2022
  2013                              <1> 	; 20/05/2015
  2014                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2015                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2016                              <1> 	;
  2017                              <1> 	; Reads from an inode whose number in R1
  2018                              <1> 	; 
  2019                              <1> 	; INPUTS ->
  2020                              <1> 	;    r1 - inode number
  2021                              <1> 	;    u.count - byte count user desires
  2022                              <1> 	;    u.base - points to user buffer
  2023                              <1> 	;    u.fofp - points to word with current file offset
  2024                              <1> 	; OUTPUTS ->
  2025                              <1> 	;    u.count - cleared
  2026                              <1> 	;    u.nread - accumulates total bytes passed back
  2027                              <1> 	;
  2028                              <1> 	; ((AX = R1)) input/output
  2029                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2030                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2031                              <1> 
  2032 000053B7 31D2                <1> 	xor	edx, edx ; 0
  2033 000053B9 8915[206F0000]      <1> 	mov 	[u.nread], edx ; 0
  2034                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2035 000053BF 668915[576F0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2036 000053C6 3915[1C6F0000]      <1> 	cmp 	[u.count], edx ; 0
  2037                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2038 000053CC 7701                <1> 	ja 	short readi_1 ; 1f
  2039                              <1> 		 ; bgt 1f / yes, branch
  2040 000053CE C3                  <1> 	retn
  2041                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2042                              <1> readi_1: ; 1:
  2043                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2044 000053CF 6683F828            <1> 	cmp	ax, 40
  2045                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2046                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2047                              <1>         ;ja	dskr 
  2048                              <1> 		 ; ble 1f / yes, branch
  2049                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2050                              <1> 		 ;         / read file with i-node number (r1)
  2051                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2052                              <1> 	; 03/02/2022
  2053 000053D3 7605                <1> 	jna	short readi_3
  2054 000053D5 E9CF000000          <1> 	jmp	dskr
  2055                              <1> readi_3:
  2056                              <1> 	; (20/05/2015)
  2057 000053DA 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2058                              <1> 	; 1:
  2059 000053DB 0FB6D8              <1> 	movzx	ebx, al
  2060                              <1> 	; 03/02/2022
  2061 000053DE C1E302              <1> 	shl	ebx, 2
  2062                              <1> 	;shl	bx, 2
  2063                              <1> 		 ; asl r1 / multiply inode number by 2
  2064 000053E1 81C3[E5530000]      <1> 	add	ebx, readi_2 - 4
  2065 000053E7 FF23                <1> 	jmp	dword [ebx]	
  2066                              <1> 		 ; jmp *1f-2(r1)
  2067                              <1> readi_2: ; 1:
  2068 000053E9 [35540000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2069                              <1> 		 ;rtty / tty; r1=2
  2070                              <1> 		 ;rppt / ppt; r1=4
  2071 000053ED [85540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2072                              <1> 		 ;rmem / mem; r1=6
  2073                              <1> 		 ;rrf0 / rf0
  2074                              <1> 		 ;rrk0 / rk0
  2075                              <1> 		 ;rtap / tap0
  2076                              <1> 		 ;rtap / tap1
  2077                              <1> 		 ;rtap / tap2
  2078                              <1> 		 ;rtap / tap3
  2079                              <1> 		 ;rtap / tap4
  2080                              <1> 		 ;rtap / tap5
  2081                              <1> 		 ;rtap / tap6
  2082                              <1> 		 ;rtap / tap7
  2083 000053F1 [745B0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2084 000053F5 [745B0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2085 000053F9 [745B0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2086 000053FD [745B0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2087 00005401 [745B0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2088 00005405 [745B0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2089 00005409 [9A540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2090 0000540D [81540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2091                              <1> 		 ;rcvt / tty0
  2092 00005411 [81540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2093                              <1> 		 ;rcvt / tty1
  2094 00005415 [81540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2095                              <1> 		 ;rcvt / tty2
  2096 00005419 [81540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2097                              <1> 		 ;rcvt / tty3
  2098 0000541D [81540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2099                              <1> 		 ;rcvt / tty4
  2100 00005421 [81540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2101                              <1> 		 ;rcvt / tty5
  2102 00005425 [81540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2103                              <1> 		 ;rcvt / tty6
  2104 00005429 [81540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2105                              <1> 		 ;rcvt / tty7
  2106 0000542D [81540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2107                              <1> 		 ;rcrd / crd
  2108 00005431 [81540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2109                              <1> 
  2110                              <1> rtty: ; / read from console tty
  2111                              <1> 	; 03/02/2022
  2112                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2113                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2114                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2115                              <1> 	;	     must be written immediate on video page (screen)
  2116                              <1> 	;	     when it is required.	
  2117                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2118                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2119                              <1> 	;
  2120                              <1> 	; Console tty buffer is PC keyboard buffer
  2121                              <1> 	; and keyboard-keystroke handling is different than original
  2122                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2123                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2124                              <1> 	;
  2125                              <1> 	; 06/12/2013
  2126 00005435 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2127 0000543C 8A83[556C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2128                              <1> rttys:
  2129                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2130                              <1> 	               ; / of the control and status block
  2131                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2132                              <1> 		       ; / tty buffer
  2133                              <1> 	; 28/07/2013
  2134 00005442 A2[466F0000]        <1> 	mov 	[u.ttyn], al
  2135                              <1> 	; 13/01/2014
  2136 00005447 FEC0                <1> 	inc	al
  2137 00005449 A2[286F0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2138                              <1> rtty_nc: ; 01/02/2014
  2139                              <1> 	; 29/09/2013
  2140                              <1> 	;mov	ecx, 10
  2141                              <1> 	; 03/02/2022
  2142 0000544E 29C9                <1> 	sub	ecx, ecx
  2143 00005450 B10A                <1> 	mov	cl, 10
  2144                              <1> rtty_1: 	; 01/02/2014
  2145                              <1> 	;push 	cx ; 29/09/2013
  2146                              <1> 	; 03/02/2022
  2147 00005452 51                  <1> 	push	ecx
  2148                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2149 00005453 B001                <1> 	mov 	al, 1
  2150 00005455 E86A0B0000          <1> 	call 	getc
  2151                              <1> 	; 03/02/2022
  2152 0000545A 59                  <1> 	pop	ecx
  2153                              <1> 	;pop 	cx ; 29/09/2013	
  2154 0000545B 7516                <1> 	jnz	short rtty_2
  2155                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2156                              <1> 	               ; / of chars. Is this number non-zero?
  2157 0000545D E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2158                              <1> 	; 05/10/2013
  2159 0000545F 8A25[466F0000]      <1> 	mov	ah, [u.ttyn]
  2160                              <1> 	; 29/09/2013
  2161 00005465 E89AFBFFFF          <1> 	call	sleep
  2162                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2163                              <1>                 ;           / (120 chars.)
  2164                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2165 0000546A EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2166                              <1> 
  2167                              <1> rtty_idle:
  2168                              <1> 	; 29/07/2013
  2169 0000546C E806FBFFFF          <1> 	call 	idle
  2170 00005471 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2171                              <1> 	;1:
  2172                              <1> 		; tst 2(r5) / is the number of characters zero
  2173                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2174                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2175                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2176                              <1> 		          ; / contains the next char.
  2177                              <1> 		; dec 2(r5) / decrement the character count
  2178                              <1> rtty_2:
  2179 00005473 30C0                <1> 	xor 	al, al
  2180 00005475 E84A0B0000          <1> 	call 	getc
  2181 0000547A E892000000          <1> 	call	passc
  2182                              <1> 		; jsr r0,passc / move the character to core (user)
  2183                              <1> 	;; 17/10/2015 - 16/07/2015
  2184                              <1> 	; 19/06/2014
  2185                              <1> 	;;jnz	short rtty_nc
  2186 0000547F 58                  <1> 	pop	eax  ; (20/05/2015)
  2187 00005480 C3                  <1> 	retn 
  2188                              <1> ;ret1:
  2189                              <1> 		; jmp ret / return to caller via 'ret'
  2190                              <1> 
  2191                              <1> rcvt:   ; < receive/read character from tty >
  2192                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2193                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2194                              <1> 	;
  2195                              <1> 	; Retro UNIX 8086 v1 modification !
  2196                              <1> 	; 
  2197                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2198                              <1> 	;		(exactly different than this one)
  2199                              <1> 	;	was in 'u9.s' file.
  2200                              <1> 	;
  2201 00005481 2C0A                <1> 	sub 	al, 10
  2202                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2203                              <1> 	; 16/07/2013
  2204                              <1> 	; 21/05/2013
  2205 00005483 EBBD                <1>         jmp     short rttys
  2206                              <1>       
  2207                              <1> ;rppt: / read paper tape
  2208                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2209                              <1> ;			 / places
  2210                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2211                              <1> ;		       / also enables read bit in prs
  2212                              <1> ;	jsr	r0,passc / place character in users buffer area
  2213                              <1> ;	br	rppt
  2214                              <1> 
  2215                              <1> rmem: ; / transfer characters from memory to a user area of core
  2216                              <1> 	; 17/10/2015
  2217                              <1> 	; 11/06/2015
  2218                              <1> 	; 24/05/2015
  2219                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2220                              <1> 	;
  2221 00005485 8B35[086F0000]      <1> 	mov     esi, [u.fofp]
  2222                              <1> rmem_1:
  2223 0000548B 8B1E                <1>         mov     ebx, [esi]        
  2224                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2225                              <1> 		               ; / to be transferred to user
  2226 0000548D FF06                <1>         inc     dword [esi] ; 17/10/2015
  2227                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2228                              <1> 			    ; / char in memory file
  2229 0000548F 8A03                <1> 	mov	al, [ebx]
  2230                              <1> 		; movb (r1),r1 / get character from memory file, 
  2231                              <1> 		             ; / put it in r1
  2232 00005491 E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2233                              <1> 			     ;  / the next byte of the users core area
  2234                              <1> 		; br rmem / continue
  2235 00005496 75F3                <1> 	jnz	short rmem_1
  2236                              <1> ret_:
  2237 00005498 58                  <1> 	pop	eax ; 09/06/2015
  2238 00005499 C3                  <1> 	retn
  2239                              <1> 
  2240                              <1> rlpr:
  2241                              <1> ;1:
  2242                              <1> ;rcrd:
  2243 0000549A C705[476F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2243 000054A2 0000                <1>
  2244 000054A4 E97AE6FFFF          <1> 	jmp	error
  2245                              <1> 		;jmp	error / see 'error' routine
  2246                              <1> 
  2247                              <1> dskr:
  2248                              <1> 	; 12/10/2015
  2249                              <1> 	; 21/08/2015
  2250                              <1> 	; 25/07/2015
  2251                              <1> 	; 10/07/2015
  2252                              <1> 	; 16/06/2015
  2253                              <1> 	; 31/05/2015
  2254                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2255                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2256                              <1> dskr_0:
  2257 000054A9 50                  <1> 	push	eax
  2258                              <1> 		; mov (sp),r1 / i-number in r1
  2259                              <1> 	; AX = i-number
  2260 000054AA E834FDFFFF          <1> 	call	iget
  2261                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2262 000054AF 0FB715[FA6B0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2263                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2264 000054B6 8B1D[086F0000]      <1> 	mov	ebx, [u.fofp]
  2265 000054BC 2B13                <1> 	sub	edx, [ebx]
  2266                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2267                              <1>         ; 12/10/2015
  2268                              <1> 	; jna     short ret_ 
  2269                              <1> 		; blos ret
  2270 000054BE 7709                <1> 	ja	short dskr_1
  2271                              <1> 	;
  2272                              <1> dskr_retn: ; 12/10/2015
  2273 000054C0 58                  <1> 	pop	eax
  2274 000054C1 C605[596F0000]00    <1> 	mov	byte [u.kcall], 0
  2275 000054C8 C3                  <1> 	retn	
  2276                              <1> dskr_1: 
  2277 000054C9 3B15[1C6F0000]      <1> 	cmp     edx, [u.count] 
  2278                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2279                              <1> 			       ; / to carry out read
  2280 000054CF 7306                <1> 	jnb	short dskr_2
  2281                              <1> 		; bhis 1f
  2282 000054D1 8915[1C6F0000]      <1> 	mov	[u.count], edx
  2283                              <1> 		; mov r2,u.count / no, just read to end of file
  2284                              <1> dskr_2: ; 1:
  2285                              <1> 	; AX = i-number
  2286 000054D7 E8A0FBFFFF          <1> 	call	mget
  2287                              <1> 		; jsr r0,mget / returns physical block number of block 
  2288                              <1> 			    ; / in file where offset points
  2289                              <1> 	; eAX = physical block number
  2290 000054DC E8E2070000          <1> 	call	dskrd
  2291                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2292                              <1> 			     ; / 1st word of data in buffer
  2293                              <1> 	; 09/06/2015
  2294 000054E1 803D[596F0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2295 000054E8 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2296 000054EA 66833D[576F0000]00  <1> 	cmp	word [u.pcount], 0
  2297 000054F2 7705                <1> 	ja	short dskr_4
  2298                              <1> dskr_3:
  2299                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2300 000054F4 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2301                              <1> dskr_4:
  2302                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2303 000054F9 E8BC020000          <1> 	call	sioreg
  2304                              <1> 		; jsr r0,sioreg
  2305 000054FE 87F7                <1> 	xchg	esi, edi
  2306                              <1> 	; eDI = file (user data) offset
  2307                              <1> 	; eSI = sector (I/O) buffer offset
  2308                              <1> 	; eCX = byte count
  2309 00005500 F3A4                <1> 	rep	movsb
  2310                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2311                              <1> 		                 ; / starting at u.base
  2312                              <1> 		; dec r3
  2313                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2314                              <1> 	; 25/07/2015
  2315                              <1> 	; eax = remain bytes in buffer
  2316                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2317 00005502 09C0                <1> 	or	eax, eax
  2318 00005504 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2319                              <1> 	; 03/08/2013
  2320                              <1> 	;pop	eax
  2321 00005506 390D[1C6F0000]      <1> 	cmp	[u.count], ecx ; 0
  2322                              <1> 		; tst u.count / all bytes read off disk
  2323                              <1> 		; bne dskr
  2324                              <1> 		; br ret
  2325                              <1>         ;ja      short dskr_0
  2326                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2327                              <1> 	;retn
  2328                              <1> 	; 12/10/2015
  2329 0000550C 76B2                <1> 	jna	short dskr_retn
  2330 0000550E 58                  <1> 	pop	eax  ; (i-node number)
  2331 0000550F EB98                <1> 	jmp	short dskr_0
  2332                              <1> 	
  2333                              <1> passc:
  2334                              <1> 	; 18/10/2015
  2335                              <1> 	; 10/07/2015
  2336                              <1> 	; 01/07/2015
  2337                              <1> 	; 08/06/2015
  2338                              <1> 	; 04/06/2015
  2339                              <1> 	; 20/05/2015
  2340                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2341                              <1> 	;
  2342                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2343                              <1> 	;		      to physical address
  2344 00005511 66833D[576F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2345                              <1> 			     ; 1-4095 --> use previous physical base address
  2346                              <1> 			     ; in [u.pbase]
  2347 00005519 7705                <1> 	ja	short passc_3
  2348                              <1> 	; 08/06/2015 - 10/07/2015
  2349 0000551B E82C000000          <1> 	call	trans_addr_w
  2350                              <1> passc_3:
  2351                              <1> 	; 19/05/2015
  2352 00005520 66FF0D[576F0000]    <1> 	dec	word [u.pcount]
  2353                              <1> 	;
  2354 00005527 8B1D[536F0000]      <1> 	mov	ebx, [u.pbase]
  2355 0000552D 8803                <1> 	mov	[ebx], al
  2356                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2357                              <1> 		               ; / users buffer
  2358 0000552F FF05[186F0000]      <1> 	inc	dword [u.base]
  2359                              <1> 		; inc u.base / increment the pointer to point to 
  2360                              <1> 			  ; / the next byte in users buffer
  2361 00005535 FF05[536F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2362 0000553B FF05[206F0000]      <1> 	inc	dword [u.nread]
  2363                              <1> 		; inc u.nread / increment the number of bytes read
  2364 00005541 FF0D[1C6F0000]      <1> 	dec	dword [u.count]
  2365                              <1> 		; dec u.count / decrement the number of bytes to be read
  2366                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2367 00005547 C3                  <1> 	retn
  2368                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2369                              <1> 		             ; / 'readi' by:
  2370                              <1> 		;/ (1) pop the return address off the stack into r0
  2371                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2372                              <1> 	;1:
  2373                              <1> 		; clr	*$ps / clear processor status
  2374                              <1> 		; rts r0 / return to address currently on top of stack
  2375                              <1> 
  2376                              <1> trans_addr_r:
  2377                              <1> 	; Translate virtual address to physical address 
  2378                              <1> 	; for reading from user's memory space
  2379                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2380                              <1> 	; 18/10/2015
  2381                              <1> 	; 10/07/2015
  2382                              <1> 	; 09/06/2015
  2383                              <1> 	; 08/06/2015 
  2384                              <1> 	; 04/06/2015
  2385                              <1> 	;
  2386                              <1> 	; 18/10/2015
  2387 00005548 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2388 0000554A EB04                <1> 	jmp 	short trans_addr_rw
  2389                              <1> 
  2390                              <1> 	;push	eax
  2391                              <1> 	;push	ebx
  2392                              <1> 	;mov	ebx, [u.base]
  2393                              <1> 	;call	get_physical_addr ; get physical address
  2394                              <1> 	;;jnc	short cpass_0
  2395                              <1> 	;jnc	short passc_1
  2396                              <1> 	;mov	[u.error], eax
  2397                              <1> 	;;pop	ebx
  2398                              <1> 	;;pop	eax
  2399                              <1> 	;jmp	error
  2400                              <1> ;cpass_0:
  2401                              <1> 	; 18/10/2015
  2402                              <1> 	; 20/05/2015
  2403                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2404                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2405                              <1> 	;pop	ebx
  2406                              <1> 	;pop	eax
  2407                              <1> 	;retn	; 08/06/2015
  2408                              <1> 
  2409                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2410                              <1> trans_addr_w:
  2411                              <1> 	; Translate virtual address to physical address 
  2412                              <1> 	; for writing to user's memory space
  2413                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2414                              <1> 	; 18/10/2015
  2415                              <1> 	; 29/07/2015
  2416                              <1> 	; 10/07/2015
  2417                              <1> 	; 09/06/2015
  2418                              <1> 	; 08/06/2015
  2419                              <1> 	; 04/06/2015 (passc)
  2420                              <1> 	;
  2421                              <1> 	; 18/10/2015
  2422 0000554C 29D2                <1> 	sub	edx, edx
  2423 0000554E FEC2                <1> 	inc	dl ; 1 (write access sign)
  2424                              <1> trans_addr_rw:
  2425 00005550 50                  <1> 	push	eax
  2426 00005551 53                  <1> 	push	ebx
  2427                              <1> 	; 18/10/2015
  2428 00005552 52                  <1> 	push 	edx ; r/w sign (in DL)
  2429                              <1> 	;
  2430 00005553 8B1D[186F0000]      <1> 	mov	ebx, [u.base]
  2431 00005559 E876DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2432 0000555E 730A                <1> 	jnc	short passc_0
  2433 00005560 A3[476F0000]        <1> 	mov	[u.error], eax
  2434                              <1> 	;pop	edx
  2435                              <1> 	;pop 	ebx
  2436                              <1> 	;pop	eax
  2437 00005565 E9B9E5FFFF          <1> 	jmp	error
  2438                              <1> passc_0:
  2439 0000556A F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2440 0000556D 5A                  <1> 	pop	edx ; 18/10/2015
  2441 0000556E 7517                <1> 	jnz	short passc_1
  2442                              <1> 	; 18/10/2015
  2443 00005570 20D2                <1> 	and 	dl, dl
  2444 00005572 7413                <1> 	jz	short passc_1
  2445                              <1> 	; 20/05/2015
  2446                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2447                              <1> 	; EBX = linear address
  2448 00005574 51                  <1> 	push 	ecx
  2449 00005575 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2450 00005576 E8C8DBFFFF          <1> 	call 	copy_page
  2451 0000557B 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2452 0000557C 59                  <1> 	pop	ecx
  2453 0000557D 7217                <1> 	jc	short passc_2
  2454                              <1> 	; 03/02/2022
  2455                              <1> 	;push	eax ; physical address of the new/allocated page
  2456                              <1> 	;call	add_to_swap_queue
  2457                              <1> 	;pop	eax
  2458                              <1> 	; 18/10/2015
  2459 0000557F 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2460                              <1> 	;mov 	ecx, PAGE_SIZE
  2461                              <1> 	;sub	ecx, ebx 
  2462 00005585 01D8                <1> 	add	eax, ebx  
  2463                              <1> passc_1: 
  2464                              <1> 	; 18/10/2015
  2465                              <1> 	; 20/05/2015
  2466 00005587 A3[536F0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2467 0000558C 66890D[576F0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2468 00005593 5B                  <1> 	pop	ebx
  2469 00005594 58                  <1> 	pop	eax
  2470 00005595 C3                  <1> 	retn	; 08/06/2015
  2471                              <1> passc_2:
  2472 00005596 C705[476F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2472 0000559E 0000                <1>
  2473                              <1> 	;pop 	ebx
  2474                              <1> 	;pop	eax
  2475 000055A0 E97EE5FFFF          <1> 	jmp	error
  2476                              <1> 
  2477                              <1> writei:
  2478                              <1> 	; 03/02/2022
  2479                              <1> 	; 20/05/2015
  2480                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2481                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2482                              <1> 	;
  2483                              <1> 	; Write data to file with inode number in R1
  2484                              <1> 	; 
  2485                              <1> 	; INPUTS ->
  2486                              <1> 	;    r1 - inode number
  2487                              <1> 	;    u.count - byte count to be written
  2488                              <1> 	;    u.base - points to user buffer
  2489                              <1> 	;    u.fofp - points to word with current file offset
  2490                              <1> 	; OUTPUTS ->
  2491                              <1> 	;    u.count - cleared
  2492                              <1> 	;    u.nread - accumulates total bytes passed back	
  2493                              <1> 	; ((AX = R1))
  2494                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2495                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2496                              <1> 
  2497 000055A5 31C9                <1> 	xor	ecx, ecx
  2498 000055A7 890D[206F0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2499                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2500                              <1> 		            ; / read or write calls
  2501 000055AD 66890D[576F0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2502 000055B4 390D[1C6F0000]      <1> 	cmp 	[u.count], ecx
  2503                              <1> 	;	; tst u.count / test the byte count specified by the user
  2504 000055BA 7701                <1> 	ja 	short writei_1 ; 1f
  2505                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2506 000055BC C3                  <1> 	retn
  2507                              <1> 	;	; rts r0 / no, return - no writing to do
  2508                              <1> writei_1: ;1:
  2509                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2510 000055BD 6683F828            <1> 	cmp 	ax, 40
  2511                              <1> 		; cmp r1,$40.
  2512                              <1> 		; / does the i-node number indicate a special file?
  2513                              <1> 	;ja	dskw 
  2514                              <1> 		; bgt dskw / no, branch to standard file output
  2515                              <1> 	; 03/02/2022
  2516 000055C1 7605                <1> 	jna	short writei_3
  2517 000055C3 E9ED000000          <1> 	jmp	dskw
  2518                              <1> writei_3:
  2519                              <1> 	; (20/05/2015)
  2520 000055C8 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2521 000055C9 0FB6D8              <1> 	movzx	ebx, al
  2522                              <1> 	; 03/02/2022
  2523 000055CC C1E302              <1> 	shl	ebx, 2
  2524                              <1> 	;shl	bx, 2
  2525                              <1> 		; asl r1 / yes, calculate the index into the special file
  2526 000055CF 81C3[D3550000]      <1> 	add	ebx, writei_2 - 4
  2527 000055D5 FF23                <1> 	jmp	dword [ebx]	
  2528                              <1> 		; jmp *1f-2(r1)
  2529                              <1> 		; / jump table and jump to the appropriate routine
  2530                              <1> writei_2: ;1:
  2531 000055D7 [23560000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2532                              <1> 		 ;wtty / tty; r1=2
  2533                              <1> 		 ;wppt / ppt; r1=4
  2534 000055DB [85560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2535                              <1> 		 ;wmem / mem; r1=6
  2536                              <1> 		 ;wrf0 / rf0
  2537                              <1> 		 ;wrk0 / rk0
  2538                              <1> 		 ;wtap / tap0
  2539                              <1> 		 ;wtap / tap1
  2540                              <1> 		 ;wtap / tap2
  2541                              <1> 		 ;wtap / tap3
  2542                              <1> 		 ;wtap / tap4
  2543                              <1> 		 ;wtap / tap5
  2544                              <1> 		 ;wtap / tap6
  2545                              <1> 		 ;wtap / tap7
  2546 000055DF [FD5B0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2547 000055E3 [FD5B0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2548 000055E7 [FD5B0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2549 000055EB [FD5B0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2550 000055EF [FD5B0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2551 000055F3 [FD5B0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2552 000055F7 [76560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2553 000055FB [70560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2554                              <1> 		 ;xmtt / tty0
  2555 000055FF [70560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2556                              <1> 		 ;xmtt / tty1
  2557 00005603 [70560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2558                              <1> 		 ;xmtt / tty2
  2559 00005607 [70560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2560                              <1> 		 ;xmtt / tty3
  2561 0000560B [70560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2562                              <1> 		 ;xmtt / tty4
  2563 0000560F [70560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2564                              <1> 		 ;xmtt / tty5
  2565 00005613 [70560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2566                              <1> 		 ;xmtt / tty6
  2567 00005617 [70560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2568                              <1> 		 ;xmtt / tty7
  2569 0000561B [70560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2570                              <1> 		; / wlpr / lpr
  2571 0000561F [70560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2572                              <1> 
  2573                              <1> wtty: ; write to console tty (write to screen)
  2574                              <1> 	; 03/02/2022
  2575                              <1> 	; 18/11/2015
  2576                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2577                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2578                              <1> 	;
  2579                              <1> 	; Console tty output is on current video page
  2580                              <1> 	; Console tty character output procedure is changed here
  2581                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2582                              <1> 	;
  2583 00005623 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2584 0000562A 8AA3[556C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2585 00005630 88E0                <1> 	mov	al, ah ; 07/07/2014
  2586                              <1> wttys:	
  2587                              <1> 	; 10/10/2013
  2588 00005632 8825[466F0000]      <1> 	mov 	[u.ttyn], ah
  2589                              <1> 	; 13/01/2014
  2590 00005638 FEC0                <1> 	inc	al
  2591 0000563A A2[296F0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2592                              <1> wtty_nc: ; 15/05/2013
  2593                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2594 0000563F E816010000          <1> 	call	cpass
  2595                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2596                              <1> 		             ; / none go to return address in syswrite
  2597                              <1> 		; tst r1 / is character = null
  2598                              <1> 		; beq wtty / yes, get next character
  2599                              <1> 	; 10/10/2013
  2600 00005644 7428                <1> 	jz	short wret
  2601                              <1> 	;1 :
  2602                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2603                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2604                              <1> 		;	          / than 20
  2605                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2606                              <1> 	; 27/06/2014
  2607                              <1> wtty_1:
  2608                              <1> 	; AH = tty number
  2609                              <1> 	; AL = ASCII code of the character
  2610                              <1> 	; 15/04/2014
  2611                              <1> 	;push	ax
  2612                              <1> 	; 03/02/2022
  2613 00005646 50                  <1> 	push	eax
  2614 00005647 E8E6090000          <1> 	call	putc ; 14/05/2013
  2615 0000564C 731D                <1> 	jnc	short wtty_2
  2616                              <1> 	; 18/11/2015
  2617 0000564E E824F9FFFF          <1> 	call	idle
  2618                              <1> 	;mov	ax, [esp]
  2619                              <1> 	; 03/02/2022
  2620 00005653 8B0424              <1> 	mov	eax, [esp]
  2621 00005656 E8D7090000          <1> 	call	putc
  2622 0000565B 730E                <1> 	jnc	short wtty_2 
  2623                              <1> 	; 02/06/2014
  2624 0000565D 8A25[466F0000]      <1> 	mov	ah, [u.ttyn]
  2625 00005663 E89CF9FFFF          <1> 	call	sleep
  2626                              <1> 	; 03/02/2022
  2627 00005668 58                  <1> 	pop	eax
  2628                              <1> 	;pop	ax
  2629 00005669 EBDB                <1> 	jmp 	short wtty_1
  2630                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2631                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2632                              <1> 			      ; / console tty and
  2633                              <1> 		; br 	2f / place character in list; if none available
  2634                              <1> 		   	  ; / branch to put process to sleep
  2635                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2636                              <1> wtty_2:
  2637                              <1> 	; 15/04/2014
  2638                              <1> 	;pop	ax
  2639                              <1> 	; 03/02/2022
  2640 0000566B 58                  <1> 	pop	eax
  2641 0000566C EBD1                <1> 	jmp	short wtty_nc
  2642                              <1> 		; br wtty
  2643                              <1> wret:	; 10/10/2013 (20/05/2015)
  2644 0000566E 58                  <1> 	pop	eax
  2645 0000566F C3                  <1> 	retn
  2646                              <1> 	;2:
  2647                              <1> 		;mov	r1,-(sp) / place character on stack
  2648                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2649                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2650                              <1> 		;br	1b / try again to place character in clist and output
  2651                              <1> 
  2652                              <1> xmtt:   ; < send/write character to tty >
  2653                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2654                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2655                              <1> 	;
  2656                              <1> 	; Retro UNIX 8086 v1 modification !
  2657                              <1> 	; 
  2658                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2659                              <1> 	;		(exactly different than this one)
  2660                              <1> 	;	was in 'u9.s' file.
  2661                              <1> 	;
  2662 00005670 2C0A                <1> 	sub 	al, 10
  2663                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2664                              <1> 	 ; 10/10/2013
  2665 00005672 88C4                <1> 	mov	ah, al
  2666                              <1> 	; 28/07/2013
  2667 00005674 EBBC                <1> 	jmp	short wttys
  2668                              <1> 
  2669                              <1> ;wppt:
  2670                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2671                              <1> ;		         / if none return to writei's calling routine
  2672                              <1> ;	jsr	r0,pptoc / output character on ppt
  2673                              <1> ;	br	wppt
  2674                              <1> wlpr:
  2675 00005676 C705[476F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2675 0000567E 0000                <1>
  2676 00005680 E99EE4FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2677                              <1> 		;/	jsr	r0,cpass
  2678                              <1> 		;/	cmp	r0,$'a
  2679                              <1> 		;/	blo	1f
  2680                              <1> 		;/	cmp	r1,$'z
  2681                              <1> 		;/	bhi	1f
  2682                              <1> 		;/	sub	$40,r1
  2683                              <1> 		;/1:
  2684                              <1> 		;/	jsr	r0,lptoc
  2685                              <1> 		;/	br	wlpr
  2686                              <1> 		; br rmem / continue
  2687                              <1> 
  2688                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2689                              <1> 	; 17/10/2015
  2690                              <1> 	; 11/06/2015
  2691                              <1> 	; 24/05/2015
  2692                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2693                              <1> 	;
  2694 00005685 813D[2D070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2694 0000568B [9A4F0000]          <1>
  2695 0000568F 7415                <1>         je      short wmem_acc_err
  2696                              <1> 	;
  2697 00005691 8B35[086F0000]      <1>         mov     esi, [u.fofp] 
  2698                              <1> wmem_1:
  2699 00005697 E8BE000000          <1> 	call	cpass
  2700                              <1> 		; jsr r0,cpass / get next character from users area of
  2701                              <1> 			     ; / core and put it in r1
  2702                              <1>         	; mov r1,-(sp) / put character on the stack
  2703                              <1> 	; 20/09/2013
  2704 0000569C 74D0                <1> 	jz	short wret ; wmem_2  
  2705 0000569E 8B1E                <1>         mov     ebx, [esi]
  2706                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2707 000056A0 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2708                              <1> 		; inc *u.fofp / increment file offset to point to next
  2709                              <1> 			    ; / available location in file
  2710 000056A2 8803                <1> 	mov	[ebx], al	
  2711                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2712                              <1> 			        ; / assigned to it
  2713 000056A4 EBF1                <1> 	jmp	short wmem_1
  2714                              <1> 		; br wmem / continue
  2715                              <1> 	;1:
  2716                              <1> 	;jmp	error / ?
  2717                              <1> ;wmem_2:	
  2718                              <1> ;	; 20/09/2013
  2719                              <1> ;	pop	ax
  2720                              <1> ;	retn
  2721                              <1> 
  2722                              <1> wmem_acc_err:
  2723 000056A6 C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2723 000056AE 0000                <1>
  2724 000056B0 E96EE4FFFF          <1> 	jmp	error
  2725                              <1> 
  2726                              <1> dskw: ; / write routine for non-special files
  2727                              <1> 	;
  2728                              <1> 	; 03/02/2022
  2729                              <1> 	; 25/07/2015
  2730                              <1> 	; 16/06/2015
  2731                              <1> 	; 09/06/2015
  2732                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2733                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2734                              <1> 	;
  2735                              <1> 	; 01/08/2013 (mkdir_w check)
  2736                              <1> 
  2737                              <1> 	;push	ax ; 26/04/2013
  2738                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2739                              <1> 	; 03/02/2022
  2740 000056B5 50                  <1> 	push	eax
  2741                              <1> 	; AX = inode number
  2742 000056B6 E828FBFFFF          <1> 	call	iget
  2743                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2744                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2745 000056BB 8B1D[086F0000]      <1>         mov     ebx, [u.fofp] 
  2746 000056C1 8B13                <1> 	mov 	edx, [ebx]
  2747                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2748                              <1> 			       ; / in the fsp entry for this file] in r2
  2749 000056C3 0315[1C6F0000]      <1> 	add 	edx, [u.count]	
  2750                              <1> 		; add u.count,r2 / no. of bytes to be written
  2751                              <1> 			       ; / + file offset is put in r2
  2752                              <1> 	; 16/06/2015        
  2753 000056C9 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2754 000056CF 760F                <1> 	jna	short dskw_0
  2755 000056D1 C705[476F0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2755 000056D9 0000                <1>
  2756 000056DB E943E4FFFF          <1> 	jmp	error
  2757                              <1> dskw_0:	
  2758 000056E0 663B15[FA6B0000]    <1> 	cmp     dx, [i.size]
  2759                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2760                              <1> 		              ; / the file?
  2761 000056E7 760C                <1> 	jna	short dskw_1
  2762                              <1> 		; blos 1f / no, branch
  2763 000056E9 668915[FA6B0000]    <1>         mov     [i.size], dx
  2764                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2765                              <1> 			      ; / file offset + no. of data bytes
  2766 000056F0 E8F8FBFFFF          <1> 	call	setimod
  2767                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2768                              <1> 		          ; / modified), stuff time of modification into
  2769                              <1> 	          	  ; / core image of i-node
  2770                              <1> dskw_1: ; 1:	
  2771 000056F5 E882F9FFFF          <1> 	call	mget
  2772                              <1> 	; eAX = Block number
  2773                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2774                              <1> 			    ; /	the next data byte
  2775                              <1> 	; eax = block number
  2776 000056FA 8B1D[086F0000]      <1> 	mov     ebx, [u.fofp]
  2777 00005700 8B13                <1> 	mov	edx, [ebx]
  2778 00005702 81E2FF010000        <1> 	and	edx, 1FFh  
  2779                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2780 00005708 750C                <1> 	jnz	short dskw_2
  2781                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2782                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2783 0000570A 813D[1C6F0000]0002- <1> 	cmp	dword [u.count], 512
  2783 00005712 0000                <1>
  2784                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2785                              <1> 				  ; / an entire block? (i.e., no. of
  2786 00005714 7305                <1> 	jnb	short dskw_3
  2787                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2788                              <1> 			; / Yes, branch. Don't have to read block
  2789                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2790                              <1>    		; / overwritten).
  2791 00005716 E8A8050000          <1> 	call	dskrd
  2792                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2793                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2794                              <1> dskw_3: ; 3:
  2795                              <1> 	; eAX (r1) = block/sector number
  2796 0000571B E815060000          <1> 	call	wslot
  2797                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2798                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2799 00005720 803D[596F0000]00    <1> 	cmp	byte [u.kcall], 0
  2800 00005727 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2801                              <1> 	;
  2802 00005729 66833D[576F0000]00  <1> 	cmp	word [u.pcount], 0
  2803 00005731 7705                <1> 	ja	short dskw_5
  2804                              <1> dskw_4:
  2805                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2806 00005733 E810FEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2807                              <1> dskw_5:
  2808                              <1> 	; eBX (r5) = system (I/O) buffer address
  2809 00005738 E87D000000          <1> 	call	sioreg
  2810                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2811                              <1> 			     ; / r1 = address of data, r2 points to location
  2812                              <1> 			     ; / in buffer in which to start writing data
  2813                              <1> 	; eSI = file (user data) offset
  2814                              <1> 	; eDI = sector (I/O) buffer offset
  2815                              <1> 	; eCX = byte count
  2816                              <1> 	;
  2817 0000573D F3A4                <1>   	rep	movsb
  2818                              <1> 		; movb (r1 )+,(r2)+ 
  2819                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2820                              <1> 		; dec r3 / decrement no. of bytes to be written
  2821                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2822                              <1> 	; 25/07/2015
  2823                              <1> 	; eax = remain bytes in buffer
  2824                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2825 0000573F 09C0                <1> 	or	eax, eax
  2826 00005741 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2827                              <1> dskw_6:
  2828 00005743 E809060000          <1> 	call	dskwr
  2829                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2830 00005748 833D[1C6F0000]00    <1>         cmp     dword [u.count], 0
  2831                              <1> 		; tst u.count / any more data to write?
  2832 0000574F 77A4                <1> 	ja	short dskw_1
  2833                              <1> 		; bne 1b / yes, branch
  2834                              <1> 	; 03/08/2013
  2835 00005751 C605[596F0000]00    <1> 	mov	byte [u.kcall], 0
  2836                              <1> 	; 20/09/2013 (;;)
  2837                              <1> 	;pop	ax
  2838                              <1> 	; 03/02/2022
  2839 00005758 58                  <1> 	pop	eax
  2840 00005759 C3                  <1> 	retn
  2841                              <1> 	;;jmp 	short dskw_ret 
  2842                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2843                              <1> 
  2844                              <1> cpass: ; / get next character from user area of core and put it in r1
  2845                              <1> 	; 18/10/2015
  2846                              <1> 	; 10/10/2015
  2847                              <1> 	; 10/07/2015
  2848                              <1> 	; 02/07/2015
  2849                              <1> 	; 01/07/2015
  2850                              <1> 	; 24/06/2015
  2851                              <1> 	; 08/06/2015
  2852                              <1> 	; 04/06/2015
  2853                              <1> 	; 20/05/2015
  2854                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2855                              <1> 	;
  2856                              <1> 	; INPUTS -> 
  2857                              <1> 	;     [u.base] = virtual address in user area
  2858                              <1> 	;     [u.count] = byte count (max.)
  2859                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2860                              <1> 	; OUTPUTS -> 
  2861                              <1> 	;     AL = the character which is pointed by [u.base]
  2862                              <1> 	;     zf = 1 -> transfer count has been completed	
  2863                              <1>         ;
  2864                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2865                              <1> 	;
  2866                              <1> 	;
  2867 0000575A 833D[1C6F0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2868                              <1> 		; tst u.count / have all the characters been transferred
  2869                              <1> 			    ; / (i.e., u.count, # of chars. left
  2870 00005761 763F                <1> 	jna	short cpass_3
  2871                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2872 00005763 FF0D[1C6F0000]      <1> 	dec	dword [u.count]
  2873                              <1> 		; dec u.count / no, decrement u.count
  2874                              <1>         ; 19/05/2015 
  2875                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2876                              <1> 	;		      to physical address
  2877 00005769 66833D[576F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2878                              <1> 			     ; 1-4095 --> use previous physical base address
  2879                              <1> 			     ; in [u.pbase]
  2880 00005771 770E                <1> 	ja	short cpass_1
  2881                              <1> 	; 02/07/2015
  2882 00005773 833D[4F6F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2883 0000577A 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2884                              <1> 	; 08/06/2015 - 10/07/2015
  2885 0000577C E8C7FDFFFF          <1> 	call	trans_addr_r
  2886                              <1> cpass_1:
  2887                              <1> 	; 02/07/2015
  2888                              <1> 	; 24/06/2015
  2889 00005781 66FF0D[576F0000]    <1> 	dec	word [u.pcount]
  2890                              <1> cpass_2: 
  2891                              <1> 	; 10/10/2015
  2892                              <1> 	; 02/07/2015
  2893 00005788 8B15[536F0000]      <1> 	mov	edx, [u.pbase]
  2894 0000578E 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  2895                              <1> 		; movb *u.base,r1 / take the character pointed to 
  2896                              <1> 				; / by u.base and put it in r1
  2897 00005790 FF05[206F0000]      <1> 	inc	dword [u.nread]
  2898                              <1> 		; inc u.nread / increment no. of bytes transferred
  2899 00005796 FF05[186F0000]      <1> 	inc	dword [u.base]
  2900                              <1> 		; inc u.base / increment the buffer address to point to the
  2901                              <1> 			   ; / next byte
  2902 0000579C FF05[536F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2903                              <1> cpass_3:
  2904 000057A2 C3                  <1> 	retn
  2905                              <1> 		; rts	r0 / next byte
  2906                              <1> 	; 1: 
  2907                              <1> 		; mov (sp)+,r0 
  2908                              <1> 		         ; / put return address of calling routine into r0
  2909                              <1> 		; mov (sp)+,r1 / i-number in r1
  2910                              <1> 		; rts r0 / non-local return
  2911                              <1> cpass_k:
  2912                              <1> 	; 02/07/2015
  2913                              <1> 	; The caller is os kernel 
  2914                              <1> 	; (get sysexec arguments from kernel's memory space)
  2915                              <1> 	;
  2916 000057A3 8B1D[186F0000]      <1> 	mov	ebx, [u.base]
  2917 000057A9 66C705[576F0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  2917 000057B1 10                  <1>
  2918 000057B2 891D[536F0000]      <1> 	mov	[u.pbase], ebx
  2919 000057B8 EBCE                <1> 	jmp	short cpass_2
  2920                              <1> 	
  2921                              <1> sioreg: 
  2922                              <1> 	; 25/07/2015
  2923                              <1> 	; 18/07/2015
  2924                              <1> 	; 02/07/2015
  2925                              <1> 	; 17/06/2015
  2926                              <1> 	; 09/06/2015
  2927                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2928                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  2929                              <1> 	;
  2930                              <1> 	; INPUTS -> 
  2931                              <1> 	;     eBX = system buffer (data) address (r5)
  2932                              <1> 	;     [u.fofp] = pointer to file offset pointer
  2933                              <1> 	;     [u.base] = virtual address of the user buffer
  2934                              <1> 	;     [u.pbase] = physical address of the user buffer
  2935                              <1> 	;     [u.count] = byte count
  2936                              <1> 	;     [u.pcount] = byte count within page frame 			
  2937                              <1> 	; OUTPUTS -> 
  2938                              <1> 	;     eSI = user data offset (r1)
  2939                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  2940                              <1> 	;     eCX = byte count (r3)
  2941                              <1> 	;     EAX = remain bytes after byte count within page frame
  2942                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  2943                              <1>         ;
  2944                              <1> 	; ((Modified registers:  EDX))
  2945                              <1>  
  2946 000057BA 8B35[086F0000]      <1>         mov     esi, [u.fofp]
  2947 000057C0 8B3E                <1>         mov     edi, [esi]
  2948                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  2949 000057C2 89F9                <1> 	mov	ecx, edi
  2950                              <1> 		; mov r2,r3 / and also to r3
  2951 000057C4 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  2952                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  2953 000057CA 81E7FF010000        <1> 	and	edi, 1FFh
  2954                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  2955 000057D0 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  2956                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  2957                              <1> 			  ; / where data is to be placed
  2958                              <1>                 ; mov u.base,r1 / address of data is in r1
  2959 000057D2 F7D9                <1> 	neg	ecx
  2960                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  2961                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  2962 000057D4 3B0D[1C6F0000]      <1> 	cmp	ecx, [u.count]
  2963                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  2964                              <1> 			       ; / to be written to the file
  2965 000057DA 7606                <1> 	jna	short sioreg_0
  2966                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  2967                              <1> 			 ; / in the file block as the number to be written
  2968 000057DC 8B0D[1C6F0000]      <1> 	mov	ecx, [u.count]
  2969                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  2970                              <1> 			       ; / bytes as the number to be written
  2971                              <1> sioreg_0:
  2972                              <1> 	; 17/06/2015
  2973 000057E2 803D[596F0000]00    <1> 	cmp	byte [u.kcall], 0 
  2974 000057E9 7613                <1> 	jna	short sioreg_1
  2975                              <1> 	; 25/07/2015
  2976                              <1> 	; the caller is 'mkdir' or 'namei'
  2977 000057EB A1[186F0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  2978 000057F0 A3[536F0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  2979 000057F5 66890D[576F0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  2980 000057FC EB0B                <1> 	jmp	short sioreg_2
  2981                              <1> sioreg_1:
  2982                              <1> 	; 25/07/2015
  2983                              <1> 	; 18/07/2015
  2984                              <1> 	; 09/06/2015 
  2985 000057FE 0FB715[576F0000]    <1> 	movzx	edx, word [u.pcount]
  2986                              <1> 		; ecx and [u.pcount] are always > 0, here
  2987 00005805 39D1                <1> 	cmp	ecx, edx	
  2988 00005807 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  2989                              <1> sioreg_2: ; 2:
  2990 00005809 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  2991                              <1> sioreg_3:
  2992 0000580B 010D[206F0000]      <1> 	add 	[u.nread], ecx
  2993                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  2994                              <1> 			         ; / during write is put into u.nread
  2995 00005811 290D[1C6F0000]      <1> 	sub 	[u.count], ecx
  2996                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  2997                              <1> 			       ; / must be written or read
  2998 00005817 010D[186F0000]      <1> 	add 	[u.base], ecx
  2999                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3000                              <1> 			      ; / data bytes
  3001 0000581D 010E                <1>         add 	[esi], ecx 
  3002                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3003                              <1> 			       ; / + old file offset
  3004                              <1> 	; 25/07/2015
  3005 0000581F 8B35[536F0000]      <1> 	mov	esi, [u.pbase]
  3006 00005825 66290D[576F0000]    <1> 	sub	[u.pcount], cx
  3007 0000582C 010D[536F0000]      <1> 	add	[u.pbase], ecx
  3008 00005832 C3                  <1>         retn
  3009                              <1> 		; rts r0
  3010                              <1> 		; transfer count > [u.pcount]
  3011                              <1> sioreg_4:
  3012                              <1> 	; 25/07/2015
  3013                              <1> 	; transfer count > [u.pcount] 
  3014                              <1> 	; (ecx > edx)
  3015 00005833 89C8                <1> 	mov	eax, ecx
  3016 00005835 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3017 00005837 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3018 00005839 EBD0                <1> 	jmp	short sioreg_3
  1995                                  %include 'u7.s'        ; 18/04/2015
  1996                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  1997                              <1> ; Last Modification: 25/02/2022
  1998                              <1> ; ----------------------------------------------------------------------------
  1999                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2000                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2001                              <1> ;
  2002                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2003                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2004                              <1> ; <Bell Laboratories (17/3/1972)>
  2005                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2006                              <1> ;
  2007                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2008                              <1> ;
  2009                              <1> ; ****************************************************************************
  2010                              <1> ; 14/11/2015
  2011                              <1> 
  2012                              <1> sysmount: ; / mount file system; args special; name
  2013                              <1> 	; 12/02/2022
  2014                              <1> 	; 04/02/2022
  2015                              <1> 	; 14/11/2015
  2016                              <1> 	; 24/10/2015
  2017                              <1> 	; 13/10/2015
  2018                              <1> 	; 10/07/2015
  2019                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2020                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2021                              <1> 	;
  2022                              <1> 	; 'sysmount' anounces to the system that a removable 
  2023                              <1> 	; file system has been mounted on a special file.
  2024                              <1> 	; The device number of the special file is obtained vihha
  2025                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2026                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2027                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2028                              <1> 	; to read file system into core, i.e. the first block on the
  2029                              <1> 	; mountable file system is read in. This block is super block
  2030                              <1> 	; for the file system. This call is super user restricted.	
  2031                              <1> 	;
  2032                              <1> 	; Calling sequence:
  2033                              <1> 	;	sysmount; special; name
  2034                              <1> 	; Arguments:
  2035                              <1> 	;	special - pointer to name of special file (device)
  2036                              <1> 	;	name -  pointer to name of the root directory of the
  2037                              <1> 	;		newly mounted file system. 'name' should 
  2038                              <1> 	;		always be a directory.
  2039                              <1> 	; Inputs: - 
  2040                              <1> 	; Outputs: -
  2041                              <1> 	; ...............................................................
  2042                              <1> 	;				
  2043                              <1> 	; Retro UNIX 8086 v1 modification: 
  2044                              <1> 	;       'sysmount' system call has two arguments; so,
  2045                              <1> 	;	* 1st argument, special is pointed to by BX register
  2046                              <1> 	;	* 2nd argument, name is in CX register
  2047                              <1> 	;
  2048                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2049                              <1> 	;	       already modified for IBM PC compatibility and 
  2050                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2051                              <1> 	
  2052                              <1> 	;call	arg2
  2053                              <1> 		; jsr r0,arg2 / get arguments special and name
  2054 0000583B 891D[106F0000]      <1> 	mov	[u.namep], ebx
  2055                              <1> 	; 12/02/2022
  2056                              <1> 	;push	ecx ; directory name
  2057 00005841 66833D[E46E0000]00  <1> 	cmp	word [mnti], 0
  2058                              <1> 		; tst mnti / is the i-number of the cross device file
  2059                              <1> 			 ; / zero?
  2060                              <1> 	;;ja	error
  2061                              <1>         	; bne errora / no, error
  2062                              <1> 	;ja	sysmnt_err0
  2063                              <1> 	; 04/02/2022
  2064 00005849 7605                <1> 	jna	short sysmnt_0
  2065 0000584B E907010000          <1> 	jmp	sysmnt_err0
  2066                              <1> sysmnt_0:
  2067                              <1> 	; 12/02/2022
  2068 00005850 51                  <1> 	push	ecx ; directory name
  2069 00005851 E8E9000000          <1> 	call	getspl
  2070                              <1> 		; jsr r0,getspl / get special files device number in r1
  2071                              <1> 	; 12/02/2022
  2072 00005856 8F05[106F0000]      <1> 	pop	dword [u.namep] ; directory name
  2073                              <1> 	; 13/10/2015
  2074                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2075                              <1> 	; 04/02/2022
  2076 0000585C 29DB                <1> 	sub	ebx, ebx
  2077 0000585E 88C3                <1> 	mov	bl, al
  2078 00005860 F683[8A660000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2079 00005867 750F                <1> 	jnz	short sysmnt_1
  2080                              <1> sysmnt_err1:
  2081 00005869 C705[476F0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2081 00005871 0000                <1>
  2082 00005873 E9ABE2FFFF          <1> 	jmp	error
  2083                              <1> sysmnt_1:
  2084                              <1> 	; 12/02/2022
  2085                              <1> 	;pop	dword [u.namep]
  2086                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2087                              <1> 				  ; / on the device
  2088                              <1> 	; 14/11/2015
  2089 00005878 53                  <1> 	push	ebx ; 13/10/2015
  2090                              <1> 		; mov r1,-(sp) / save the device number
  2091                              <1>         ;
  2092 00005879 E89BF1FFFF          <1> 	call	namei
  2093                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2094                              <1> 		       ; ax = 0 -> file not found 	
  2095                              <1> 	;jz	error
  2096                              <1> 	;jc	error
  2097                              <1> 		; jsr r0,namei / get the i-number of the file
  2098                              <1>                	; br errora
  2099 0000587E 730F                <1> 	jnc	short sysmnt_2
  2100                              <1> sysmnt_err2:
  2101 00005880 C705[476F0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2101 00005888 0000                <1>
  2102 0000588A E994E2FFFF          <1> 	jmp	error
  2103                              <1> sysmnt_2:	
  2104 0000588F 66A3[E46E0000]      <1> 	mov	[mnti], ax
  2105                              <1>         	; mov r1,mnti / put it in mnti
  2106                              <1> 	; 04/02/2022
  2107 00005895 BB[B07D0000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2108                              <1> sysmnt_3: ;1:
  2109                              <1>         ;cmp	byte [ebx+1], 0
  2110                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2111                              <1> 			   ; / dismountable device set?
  2112                              <1>         ;jna	short sysmnt_4		
  2113                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2114                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2115                              <1> 	;jmp	short sysmnt_3
  2116                              <1> sysmnt_4:   
  2117 0000589A 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2118 0000589B A2[E16E0000]        <1> 	mov	[mdev], al
  2119                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2120 000058A0 8803                <1> 	mov	[ebx], al
  2121                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2122                              <1> 			      ; / of the I/O queue entry
  2123                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2124                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2125 000058A2 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2126                              <1> 		; bis $2000,sb1 / set the read bit
  2127                              <1> 	; Retro UNIX 386 v1 modification : 
  2128                              <1> 	;	32 bit block number at buffer header offset 4
  2129 000058A7 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2130 000058AE E8E9050000          <1> 	call 	diskio
  2131 000058B3 7345                <1> 	jnc	short sysmnt_5
  2132 000058B5 31C0                <1> 	xor 	eax, eax
  2133 000058B7 66A3[E46E0000]      <1> 	mov	[mnti], ax ; 0
  2134 000058BD A2[E16E0000]        <1> 	mov	[mdev], al ; 0
  2135                              <1> 	;mov	[cdev], al ; 0
  2136                              <1> 	; 12/02/2022
  2137 000058C2 803D[5A6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2138 000058C9 7508                <1> 	jne	short sysmnt_err3
  2139                              <1> 	; yes, clear [u.brwdev] for next check
  2140                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2141 000058CB FE05[5A6F0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2142 000058D1 EB0A                <1> 	jmp	short sysmnt_err4
  2143                              <1> sysmnt_err3:	; 12/02/2022
  2144                              <1> 	; no, set [u.error] to disk read error
  2145 000058D3 C705[476F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2145 000058DB 0000                <1>
  2146                              <1> sysmnt_err4:
  2147                              <1> 	; 12/02/2022
  2148                              <1> 	; 14/11/2015
  2149 000058DD FEC8                <1> 	dec 	al
  2150 000058DF 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2151 000058E1 FEC0                <1> 	inc	al
  2152 000058E3 48                  <1> 	dec	eax
  2153 000058E4 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2154 000058E7 E937E2FFFF          <1> 	jmp	error
  2155                              <1> sysmnt_invd:
  2156                              <1> 	; 12/02/2022
  2157 000058EC C705[476F0000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2157 000058F4 0000                <1>
  2158                              <1> 				 ;'invalid fs/superblock !' error
  2159 000058F6 30C0                <1> 	xor	al, al
  2160 000058F8 EBE3                <1> 	jmp	short sysmnt_err4
  2161                              <1> 
  2162                              <1> sysmnt_5:
  2163                              <1> 	; 04/02/2022 (BugFix)
  2164                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2165                              <1> 	; (Following check is needed to prevent mounting an
  2166                              <1> 	; invalid valid file system (invalid super block).
  2167                              <1> 	; 
  2168 000058FA 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2169 000058FD C0E002              <1> 	shl	al, 2 ; 4*index
  2170 00005900 8B88[6E660000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2171                              <1> 	;;shl 	ecx, 3 ; !!!
  2172                              <1> 	; 04/02/2022
  2173 00005906 C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2174                              <1> 	; ecx = number of free map bytes (required)
  2175                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2176 00005909 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2177                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2178                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2179 0000590D 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2180                              <1> 			 ; (in sectors), if they are not equal
  2181                              <1> 			 ; the disk to be mounted is an...	
  2182 0000590F 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2183                              <1> 			 ; (which has not got a valid super block)
  2184                              <1> 	;
  2185 00005911 C6430100            <1> 	mov	byte [ebx+1], 0
  2186                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2187                              <1> ;sysmnt_6: ;1:
  2188                              <1> 	;;cmp	byte [sb1+1], 0
  2189                              <1> 		; tstb sb1+1 / done reading?
  2190                              <1>    	;;jna	sysret
  2191                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2192                              <1> 	;;jmp	short sysmnt_6
  2193                              <1> 		;bne 1b / no, wait
  2194                              <1>         	;br sysreta / yes
  2195 00005915 E929E2FFFF          <1> 	jmp	sysret
  2196                              <1> 
  2197                              <1> sysumount: ; / special dismount file system
  2198                              <1> 	; 04/02/2022
  2199                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2200                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2201                              <1> 	;
  2202                              <1> 	; 04/11/2013
  2203                              <1> 	; 09/07/2013
  2204                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2205                              <1> 	; indicated as an argument is no longer contain a removable
  2206                              <1> 	; file system. 'getspl' gets the device number of the special
  2207                              <1> 	; file. If no file system was mounted on that device an error
  2208                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2209                              <1> 	; to 'sysret'.
  2210                              <1> 	;
  2211                              <1> 	; Calling sequence:
  2212                              <1> 	;	sysmount; special
  2213                              <1> 	; Arguments:
  2214                              <1> 	;	special - special file to dismount (device)
  2215                              <1> 	;
  2216                              <1> 	; Inputs: - 
  2217                              <1> 	; Outputs: -
  2218                              <1> 	; ...............................................................
  2219                              <1> 	;				
  2220                              <1> 	; Retro UNIX 8086 v1 modification: 
  2221                              <1> 	;       'sysumount' system call has one argument; so,
  2222                              <1> 	;	* Single argument, special is pointed to by BX register
  2223                              <1> 	;
  2224                              <1> 	
  2225                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2226                              <1> 	;call	arg
  2227                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2228 0000591A 891D[106F0000]      <1>         mov	[u.namep], ebx
  2229 00005920 E81A000000          <1> 	call	getspl
  2230                              <1> 		; jsr r0,getspl / get the device number in r1
  2231 00005925 3A05[E16E0000]      <1> 	cmp	al, [mdev]
  2232                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2233 0000592B 752A                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2234                              <1> 	;jne	error
  2235                              <1>         	; bne errora / no error
  2236 0000592D 30C0                <1> 	xor	al, al ; ah = 0
  2237                              <1> sysumnt_0: ;1:
  2238                              <1>      	; 04/02/2022
  2239                              <1> 	;cmp 	[sb1+1], al ; 0
  2240                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2241                              <1> 	;		   ; / (inhibit bit set)?
  2242                              <1> 	;jna	short sysumnt_1		
  2243                              <1> 	;	; bne 1b / yes, wait
  2244                              <1> 	;call	idle ; (wait for hardware interrupt)
  2245                              <1> 	;jmp	short sysumnt_0
  2246                              <1> sysumnt_1:        
  2247 0000592F A2[E16E0000]        <1> 	mov	[mdev], al
  2248                              <1> 	     	; clr mntd / no, clear these
  2249 00005934 66A3[E46E0000]      <1>    	mov	[mnti], ax
  2250                              <1>         	; clr mnti
  2251 0000593A E904E2FFFF          <1>         jmp	sysret
  2252                              <1> 		; br sysreta / return
  2253                              <1> 
  2254                              <1> getspl: ; / get device number from a special file name
  2255 0000593F E8D5F0FFFF          <1> 	call	namei
  2256                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2257                              <1> 		       ; ax = 0 -> file not found 	
  2258                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2259                              <1> 	; 04/02/2022
  2260 00005944 7305                <1> 	jnc	short getspl_0
  2261 00005946 E935FFFFFF          <1> 	jmp	sysmnt_err2
  2262                              <1> getspl_0:
  2263                              <1> 	;jz	error
  2264                              <1> 	;jc	error
  2265                              <1> 		; jsr r0,namei / get the i-number of the special file
  2266                              <1>                 ; br errora / no such file
  2267 0000594B 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2268                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2269                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2270 0000594F 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2271                              <1> 	;jc	error
  2272                              <1> 		; ble errora / less than 0?  yes, error
  2273 00005951 6683F805            <1>         cmp	ax, 5 ;
  2274                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2275                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2276                              <1> 	;;ja	error
  2277                              <1>         ;	; bgt errora / yes, error
  2278                              <1>         ; 04/02/2022
  2279 00005955 760F                <1> 	jna	short getspl_retn
  2280                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2281                              <1> ;iopen_retn:
  2282                              <1> ;	retn
  2283                              <1> 		; rts r0 / return with device number in r1
  2284                              <1> sysmnt_err0:
  2285 00005957 C705[476F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2285 0000595F 0000                <1>
  2286 00005961 E9BDE1FFFF          <1> 	jmp	error
  2287                              <1> 
  2288                              <1> getspl_retn:
  2289                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2290                              <1> 	; 04/02/2022
  2291                              <1> iopen_retn:
  2292 00005966 C3                  <1> 	retn
  2293                              <1> 
  2294                              <1> iopen:
  2295                              <1> 	; 04/02/2022
  2296                              <1> 	; 19/05/2015
  2297                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2298                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2299                              <1> 	;
  2300                              <1> 	; open file whose i-number is in r1
  2301                              <1> 	; 
  2302                              <1> 	; INPUTS ->
  2303                              <1> 	;    r1 - inode number
  2304                              <1> 	; OUTPUTS ->
  2305                              <1> 	;    file's inode in core	
  2306                              <1> 	;    r1 - inode number (positive)
  2307                              <1> 	;
  2308                              <1> 	; ((AX = R1))
  2309                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2310                              <1> 	;        
  2311                              <1> ; / open file whose i-number is in r1
  2312 00005967 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2313                              <1> 		; tst r1 / write or read access?
  2314 0000596A 7568                <1>         jnz	short iopen_2
  2315                              <1> 		; blt 2f / write, go to 2f
  2316 0000596C B202                <1> 	mov	dl, 2 ; read access
  2317 0000596E E844F9FFFF          <1> 	call	access
  2318                              <1>         	; jsr r0,access; 2 
  2319                              <1> 	; / get inode into core with read access
  2320                              <1> 	; DL=2
  2321                              <1> iopen_0:
  2322 00005973 6683F828            <1>         cmp	ax, 40
  2323                              <1> 		; cmp r1,$40. / is it a special file
  2324 00005977 77ED                <1>         ja	short iopen_retn
  2325                              <1> 		; bgt 3f / no. 3f
  2326                              <1> 	; 04/02/2022
  2327 00005979 50                  <1> 	push	eax
  2328                              <1> 	;push	ax
  2329                              <1> 		; mov r1,-(sp) / yes, figure out
  2330 0000597A 0FB6D8              <1> 	movzx	ebx, al
  2331 0000597D C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2332                              <1> 	;shl	bx, 2
  2333                              <1> 		; asl r1
  2334 00005980 81C3[84590000]      <1>         add     ebx, iopen_1 - 4
  2335 00005986 FF23                <1> 	jmp	dword [ebx]
  2336                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2337                              <1> iopen_1: ; 1:
  2338 00005988 [EC590000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2339                              <1>  		 ;otty / tty ; r1=2
  2340                              <1>         	 ;oppt / ppt ; r1=4
  2341 0000598C [A45A0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2342                              <1> 		 ;sret / mem ; r1=6
  2343                              <1> 		 ;sret / rf0
  2344                              <1>         	 ;sret / rk0
  2345                              <1>         	 ;sret / tap0
  2346                              <1>         	 ;sret / tap1
  2347                              <1>         	 ;sret / tap2
  2348                              <1>         	 ;sret / tap3
  2349                              <1>         	 ;sret / tap4
  2350                              <1>         	 ;sret / tap5
  2351                              <1>         	 ;sret / tap6
  2352                              <1>         	 ;sret / tap7
  2353 00005990 [A45A0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2354 00005994 [A45A0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2355 00005998 [A45A0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2356 0000599C [A45A0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2357 000059A0 [A45A0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2358 000059A4 [A45A0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2359                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2360 000059A8 [A45A0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2361 000059AC [FD590000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2362                              <1> 		 ;ocvt / tty0
  2363 000059B0 [FD590000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2364                              <1> 		 ;ocvt / tty1
  2365 000059B4 [FD590000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2366                              <1> 		 ;ocvt / tty2
  2367 000059B8 [FD590000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2368                              <1> 		 ;ocvt / tty3
  2369 000059BC [FD590000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2370                              <1> 		 ;ocvt / tty4
  2371 000059C0 [FD590000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2372                              <1> 		 ;ocvt / tty5
  2373 000059C4 [FD590000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2374                              <1> 		 ;ocvt / tty6
  2375 000059C8 [FD590000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2376                              <1> 		 ;ocvt / tty7
  2377 000059CC [FD590000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2378                              <1> 		 ;error / crd
  2379 000059D0 [FD590000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2380                              <1> 
  2381                              <1> iopen_2: ; 2: / check open write access
  2382 000059D4 66F7D8              <1> 	neg	ax
  2383                              <1> 		; neg r1 / make inode number positive
  2384 000059D7 B201                <1> 	mov	dl, 1 ; write access
  2385 000059D9 E8D9F8FFFF          <1> 	call	access
  2386                              <1> 		; jsr r0,access; 1 / get inode in core
  2387                              <1> 	; DL=1
  2388                              <1> 	; 04/02/2022
  2389 000059DE F605[F76B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2390                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2391                              <1>  		; bit $40000,i.flgs / is it a directory?
  2392 000059E5 748C                <1> 	jz	short iopen_0
  2393                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2394                              <1> 	;jmp	error ; permission denied !
  2395 000059E7 E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2396                              <1> 	;;jnz	error		
  2397                              <1>        		; bne 2f / yes, transfer (error)
  2398                              <1>         ;;jmp	short iopen_0
  2399                              <1> 	;cmp	ax, 40
  2400                              <1> 		; cmp r1,$40. / no, is it a special file?
  2401                              <1>         ;ja	short iopen_2
  2402                              <1> 		; bgt 3f / no, return
  2403                              <1> 	;push	ax
  2404                              <1> 		; mov r1,-(sp) / yes
  2405                              <1> 	;movzx	ebx, al
  2406                              <1> 	;shl	bx, 1
  2407                              <1> 		; asl r1
  2408                              <1> 	;add	ebx, ipen_3 - 2
  2409                              <1> 	;jmp	dword [ebx]
  2410                              <1> 		; jmp *1f-2(r1) / figure out 
  2411                              <1> 			; / which special file it is and transfer
  2412                              <1> ;iopen_3: ; 1:
  2413                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2414                              <1>  		 ;otty / tty ; r1=2
  2415                              <1>         	 ;leadr / ppt ; r1=4
  2416                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2417                              <1> 		 ;sret / mem ; r1=6
  2418                              <1> 		 ;sret / rf0
  2419                              <1>         	 ;sret / rk0
  2420                              <1>         	 ;sret / tap0
  2421                              <1>         	 ;sret / tap1
  2422                              <1>         	 ;sret / tap2
  2423                              <1>         	 ;sret / tap3
  2424                              <1>         	 ;sret / tap4
  2425                              <1>         	 ;sret / tap5
  2426                              <1>         	 ;sret / tap6
  2427                              <1>         	 ;sret / tap7
  2428                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2429                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2430                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2431                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2432                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2433                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2434                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2435                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2436                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2437                              <1> 		 ;ocvt / tty0
  2438                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2439                              <1> 		 ;ocvt / tty1
  2440                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2441                              <1> 		 ;ocvt / tty2
  2442                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2443                              <1> 		 ;ocvt / tty3
  2444                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2445                              <1> 		 ;ocvt / tty4
  2446                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2447                              <1> 		 ;ocvt / tty5
  2448                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2449                              <1> 		 ;ocvt / tty6
  2450                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2451                              <1> 		 ;ocvt / tty7
  2452                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2453                              <1> 		 ;/ ejec / lpr
  2454                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2455                              <1> 
  2456                              <1> otty: ;/ open console tty for reading or writing
  2457                              <1> 	; 23/02/2022
  2458                              <1> 	; 22/02/2022
  2459                              <1> 	; 04/02/2022
  2460                              <1> 	; 16/11/2015
  2461                              <1> 	; 12/11/2015
  2462                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2463                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2464                              <1> 	; 16/07/2013
  2465                              <1> 	; Retro UNIX 8086 v1 modification:
  2466                              <1> 	;  If a tty is open for read or write by
  2467                              <1> 	;     a process (u.uno), only same process can open
  2468                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2469                              <1> 	;
  2470                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2471                              <1> 	;
  2472 000059EC 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2473 000059F3 8A83[556C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2474                              <1> 	; 13/01/2014
  2475                              <1> 	;jmp	short ottyp
  2476                              <1> 	; 23/02/2022
  2477 000059F9 88C4                <1> 	mov	ah, al
  2478 000059FB EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2479                              <1> ocvt:
  2480 000059FD 2C0A                <1> 	sub	al, 10
  2481                              <1> 	; 04/02/2022
  2482 000059FF 31DB                <1> 	xor	ebx, ebx
  2483                              <1> ottyp:
  2484                              <1> 	; 23/02/2022
  2485 00005A01 B4FF                <1> 	mov	ah, 0FFh
  2486                              <1> ottypc:
  2487                              <1> 	; 23/02/2022
  2488                              <1> 	; 22/02/2022
  2489                              <1> 	; 12/02/2022
  2490                              <1> 	; 04/02/2022
  2491                              <1> 	; 16/11/2015
  2492                              <1> 	; 12/11/2015
  2493                              <1> 	; 18/05/2015 (32 bit modifications)
  2494                              <1> 	; 06/12/2013 - 13/07/2014
  2495 00005A03 88C6                <1> 	mov	dh, al ; tty number
  2496                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2497                              <1> 	; 04/02/2022
  2498 00005A05 88C3                <1> 	mov	bl, al
  2499 00005A07 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2500                              <1> 	; 26/01/2014	
  2501 00005A09 81C3[946B0000]      <1> 	add 	ebx, ttyl
  2502 00005A0F 668B0B              <1> 	mov 	cx, [ebx]
  2503                              <1> 		   ; CL = lock value (0 or process number)
  2504                              <1> 		   ; CH = open count 
  2505 00005A12 20C9                <1> 	and 	cl, cl
  2506                              <1> 	; 13/01/2014
  2507                              <1> 	;jz 	short otty_ret
  2508                              <1> 	; 04/02/2022
  2509 00005A14 7447                <1> 	jz 	short ottys_0
  2510                              <1> 	;
  2511                              <1> 	; 16/11/2015
  2512 00005A16 3A0D[416F0000]      <1> 	cmp 	cl, [u.uno]
  2513 00005A1C 7472                <1> 	je	short ottys_3
  2514                              <1> 	;
  2515                              <1> 	; 23/02/2022
  2516                              <1> 	; (is it the console tty of the current process?)
  2517                              <1> 	; ((fast check/permit for console tty open function))
  2518 00005A1E 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2519 00005A20 746E                <1> 	je	short ottys_3 ; bypass parent process check
  2520                              <1> 	;
  2521                              <1> 	; 22/02/2022
  2522                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2523                              <1> 	;shl 	bl, 1
  2524                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2525                              <1> 	;;movzx ebx, byte [u.uno]
  2526                              <1> 	;mov	bl, [u.uno]
  2527                              <1> 	;shl 	bl, 1
  2528                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2529                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2530                              <1> 	; 22/02/2022 (BugFix) ; *
  2531 00005A22 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2532 00005A25 D1E6                <1> 	shl 	esi, 1
  2533 00005A27 668B86[146C0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2534 00005A2E 96                  <1> 	xchg	esi, eax
  2535 00005A2F A0[416F0000]        <1> 	mov	al, [u.uno]
  2536 00005A34 D0E0                <1> 	shl 	al, 1
  2537 00005A36 663BB0[346C0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2538 00005A3D 7451                <1> 	je 	short ottys_3 ; *
  2539                              <1> 	; 23/02/2022
  2540                              <1> 	; check console tty of the process
  2541                              <1> 	; (open permission must be given if the -requested- tty is
  2542                              <1> 	;  console tty of current process)
  2543 00005A3F D0E8                <1> 	shr	al, 1
  2544 00005A41 38B0[556C0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2545 00005A47 7447                <1> 	je 	short ottys_3
  2546                              <1> 	;
  2547                              <1> 	; the tty is locked by another process
  2548                              <1> 	; except the parent process (p.ppid)
  2549                              <1>         ;
  2550                              <1> 	; 09/02/2022
  2551                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2552                              <1> 	;		; permission denied ! error
  2553                              <1> otty_err: ; 13/01/2014
  2554                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2555                              <1> 	;;jnz	error
  2556                              <1> 	; 04/02/2022
  2557                              <1> 	;jz	short otty_stc_retn
  2558                              <1> 	;jmp	error
  2559                              <1> 	; 12/02/2022
  2560 00005A49 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2561 00005A4C 725B                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2562                              <1> 	; iopen (dl=1 or dl=2)
  2563 00005A4E C705[476F0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2563 00005A56 0000                <1>
  2564                              <1> 			; permission denied ! error
  2565 00005A58 E9C6E0FFFF          <1> 	jmp	error
  2566                              <1> ;otty_stc_retn:
  2567                              <1> 	;stc
  2568                              <1> 	;retn
  2569                              <1> ottys_0:
  2570                              <1> 	; 04/02/2022
  2571                              <1> otty_ret: 
  2572                              <1> 	; 13/01/2014
  2573 00005A5D 80FE07              <1> 	cmp 	dh, 7
  2574 00005A60 7624                <1> 	jna	short ottys_2
  2575                              <1> 	; 16/11/2015
  2576                              <1> com_port_check:
  2577 00005A62 BE[B26B0000]        <1> 	mov	esi, com1p
  2578 00005A67 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2579 00005A6A 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2580 00005A6C 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2581                              <1> ottys_1:
  2582                              <1> 	; 12/11/2015
  2583 00005A6D 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2584 00005A70 7714                <1> 	ja	short com_port_ready
  2585                              <1> 	;
  2586                              <1> 	; 12/02/2022
  2587 00005A72 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2588 00005A75 7232                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2589 00005A77 C705[476F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2589 00005A7F 0000                <1>
  2590                              <1> 			   ; device not ready ! error
  2591                              <1> 	;jmp	short otty_err
  2592 00005A81 E99DE0FFFF          <1> 	jmp	error
  2593                              <1> com_port_ready:
  2594                              <1> ottys_2:
  2595 00005A86 08C9                <1> 	or	cl, cl  ; cl = lock/owner, ch = open count
  2596 00005A88 7506                <1> 	jnz	short ottys_3
  2597 00005A8A 8A0D[416F0000]      <1> 	mov	cl, [u.uno]
  2598                              <1> ottys_3:
  2599 00005A90 FEC5                <1> 	inc 	ch
  2600 00005A92 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2601                              <1> 	; 06/12/2013
  2602 00005A95 FEC6                <1> 	inc	dh	; tty number + 1
  2603 00005A97 BB[286F0000]        <1> 	mov	ebx, u.ttyp
  2604                              <1> 	; 13/01/2014
  2605 00005A9C F6C202              <1> 	test	dl, 2	; open for read sign
  2606 00005A9F 7501                <1> 	jnz	short ottys_4
  2607 00005AA1 43                  <1> 	inc	ebx
  2608                              <1> ottys_4:
  2609                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2610 00005AA2 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2611                              <1> sret:
  2612 00005AA4 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2613 00005AA6 7401                <1> 	jz	short iclose_retn
  2614                              <1> 	;pop 	ax
  2615                              <1> 	; 04/02/2022
  2616 00005AA8 58                  <1> 	pop	eax
  2617                              <1> otty_retn:	; 12/02/2022
  2618                              <1> iclose_retn:	
  2619 00005AA9 C3                  <1> 	retn
  2620                              <1> 
  2621                              <1> 	;
  2622                              <1> 	; Original UNIX v1 'otty' routine:
  2623                              <1> 	;	
  2624                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2625                              <1>         ;                 / reader status reg
  2626                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2627                              <1>         ;                 / punch status reg
  2628                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2629                              <1>         ;                          / console tty buffer
  2630                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2631                              <1>         ;            / console tty
  2632                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2633                              <1>         ;             / buffer header
  2634                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2635                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2636                              <1>         ;                 / tty
  2637                              <1>         ;br     sret / ?
  2638                              <1> ;sret:
  2639                              <1> 		; clr *$ps / set processor priority to zero
  2640                              <1> ;	pop	ax
  2641                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2642                              <1> ;3:
  2643                              <1> ;	retn
  2644                              <1>         	; rts r0
  2645                              <1> 	
  2646                              <1> ;ocvt:	; < open tty >
  2647                              <1> 	; 13/01/2014
  2648                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2649                              <1> 	; 24/09/2013 consistency check -> ok
  2650                              <1> 	; 16/09/2013
  2651                              <1> 	; 03/09/2013
  2652                              <1> 	; 27/08/2013
  2653                              <1> 	; 16/08/2013
  2654                              <1> 	; 16/07/2013
  2655                              <1> 	; 27/05/2013
  2656                              <1> 	; 21/05/2013
  2657                              <1> 	;
  2658                              <1> 	; Retro UNIX 8086 v1 modification !
  2659                              <1> 	; 
  2660                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2661                              <1> 	;		(exactly different than this one)
  2662                              <1> 	;	was in 'u9.s' file.
  2663                              <1> 	;
  2664                              <1> 	; 16/07/2013
  2665                              <1> 	; Retro UNIX 8086 v1 modification:
  2666                              <1> 	;  If a tty is open for read or write by
  2667                              <1> 	;     a process (u.uno), only same process can open
  2668                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2669                              <1> 	;
  2670                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2671                              <1> 
  2672                              <1> 	; 16/09/2013
  2673                              <1> 	; sub 	al, 10
  2674                              <1> 	
  2675                              <1> 	; 06/12/2013
  2676                              <1> 	;cmp	al, 7
  2677                              <1>         ;jna     short ottyp
  2678                              <1> 	; 13/01/2014
  2679                              <1> 	;jmp	short ottyp
  2680                              <1> 
  2681                              <1> 
  2682                              <1> ;oppt: / open paper tape for reading or writing
  2683                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2684                              <1> ;        tstb   pptiflg / is file already open
  2685                              <1> ;        bne    2f / yes, branch
  2686                              <1> ;1:
  2687                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2688                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2689                              <1> ;               br .+4 / for paper tape input and place in free list
  2690                              <1> ;        br     1b
  2691                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2692                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2693                              <1> ;        br     sret
  2694                              <1> ;2:
  2695                              <1> ;        jmp    error / file already open
  2696                              <1> 
  2697                              <1> iclose: 
  2698                              <1> 	; 04/02/2022
  2699                              <1> 	; 19/05/2015
  2700                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2701                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2702                              <1> 	;
  2703                              <1> 	; close file whose i-number is in r1
  2704                              <1> 	; 
  2705                              <1> 	; INPUTS ->
  2706                              <1> 	;    r1 - inode number
  2707                              <1> 	; OUTPUTS ->
  2708                              <1> 	;    file's inode in core	
  2709                              <1> 	;    r1 - inode number (positive)
  2710                              <1> 	;
  2711                              <1> 	; ((AX = R1))
  2712                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2713                              <1> 	;        
  2714                              <1> ;/ close file whose i-number is in r1
  2715 00005AAA B202                <1> 	mov	dl, 2 ; 12/01/2014
  2716 00005AAC F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2717                              <1> 		; tst r1 / test i-number
  2718                              <1>         ;jnz	short iclose_2
  2719                              <1> 		; blt 2f / if neg., branch
  2720 00005AAF 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2721                              <1> 	; 16/07/2013 
  2722 00005AB1 66F7D8              <1> 	neg	ax ; make it positive
  2723                              <1> 	; 12/01/2014
  2724 00005AB4 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2725                              <1> iclose_0:
  2726 00005AB6 6683F828            <1> 	cmp	ax, 40
  2727                              <1> 		; cmp r1,$40. / is it a special file
  2728 00005ABA 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2729                              <1> 		; bgt 3b / no, return
  2730                              <1> 	; 12/01/2014
  2731                              <1> 	; DL=2 -> special file was opened for reading
  2732                              <1> 	; DL=1 -> special file was opened for writing
  2733                              <1> 	; 04/02/2022
  2734 00005ABC 50                  <1> 	push	eax
  2735                              <1> 	;push	ax
  2736                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2737 00005ABD 0FB6D8              <1> 	movzx	ebx, al
  2738                              <1> 	; 04/02/2022
  2739 00005AC0 C0E302              <1> 	shl	bl, 2
  2740                              <1> 	;shl	bx, 2
  2741                              <1> 		; asl r1
  2742 00005AC3 81C3[C75A0000]      <1> 	add	ebx, iclose_1 - 4
  2743 00005AC9 FF23                <1> 	jmp	dword [ebx]
  2744                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2745                              <1> iclose_1 :
  2746 00005ACB [175B0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2747 00005ACF [725B0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2748 00005AD3 [725B0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2749 00005AD7 [725B0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2750 00005ADB [725B0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2751 00005ADF [725B0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2752 00005AE3 [725B0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2753 00005AE7 [725B0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2754 00005AEB [725B0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2755                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2756                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2757 00005AEF [265B0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2758 00005AF3 [265B0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2759 00005AF7 [265B0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2760 00005AFB [265B0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2761 00005AFF [265B0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2762 00005B03 [265B0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2763 00005B07 [265B0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2764 00005B0B [265B0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2765 00005B0F [265B0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2766 00005B13 [265B0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2767                              <1> 
  2768                              <1> 	; 1:
  2769                              <1> 	;        ctty   / tty
  2770                              <1> 	;        cppt   / ppt
  2771                              <1> 	;        sret   / mem
  2772                              <1> 	;        sret   / rf0
  2773                              <1> 	;        sret   / rk0
  2774                              <1> 	;        sret   / tap0
  2775                              <1> 	;        sret   / tap1
  2776                              <1> 	;        sret   / tap2
  2777                              <1> 	;        sret   / tap3
  2778                              <1> 	;        sret   / tap4
  2779                              <1> 	;        sret   / tap5
  2780                              <1> 	;        sret   / tap6
  2781                              <1> 	;        sret   / tap7
  2782                              <1> 	;        ccvt   / tty0
  2783                              <1> 	;        ccvt   / tty1
  2784                              <1> 	;        ccvt   / tty2
  2785                              <1> 	;        ccvt   / tty3
  2786                              <1> 	;        ccvt   / tty4
  2787                              <1> 	;        ccvt   / tty5
  2788                              <1> 	;        ccvt   / tty6
  2789                              <1> 	;        ccvt   / tty7
  2790                              <1> 	;        error / crd
  2791                              <1> 
  2792                              <1> ;iclose_2: ; 2: / negative i-number
  2793                              <1> 	;neg	ax
  2794                              <1> 		;neg r1 / make it positive
  2795                              <1> 	;cmp	ax, 40
  2796                              <1> 		;cmp r1,$40. / is it a special file?
  2797                              <1>         ;ja	short @b
  2798                              <1> 		;bgt    3b / no. return
  2799                              <1> 	;push	ax
  2800                              <1> 		;mov r1,-(sp)
  2801                              <1> 	;movzx	ebx, al
  2802                              <1> 	;shl	bx, 1
  2803                              <1> 		;asl r1 / yes. compute jump address and transfer
  2804                              <1> 	;add	ebx, iclose_3 - 2
  2805                              <1> 	;jmp	dword [ebx]
  2806                              <1> 		;jmp *1f-2(r1) / figure out 
  2807                              <1> ;iclose_3:
  2808                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2809                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2810                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2811                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2812                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2813                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2814                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2815                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2816                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2817                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2818                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2819                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2820                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2821                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2822                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2823                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2824                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2825                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2826                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2827                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2828                              <1> 	
  2829                              <1> 	;1:
  2830                              <1> 	;      	ctty   / tty
  2831                              <1> 	;       leadr  / ppt
  2832                              <1> 	;       sret   / mem
  2833                              <1> 	;       sret   / rf0
  2834                              <1> 	;       sret   / rk0
  2835                              <1> 	;       sret   / tap0
  2836                              <1> 	;       sret   / tap1
  2837                              <1> 	;       sret   / tap2
  2838                              <1> 	;       sret   / tap3
  2839                              <1> 	;       sret   / tap4
  2840                              <1> 	;       sret   / tap5
  2841                              <1> 	;       sret   / tap6
  2842                              <1> 	;       sret   / tap7
  2843                              <1> 	;       ccvt   / tty0
  2844                              <1> 	;       ccvt   / tty1
  2845                              <1> 	;       ccvt   / tty2
  2846                              <1> 	;       ccvt   / tty3
  2847                              <1> 	;       ccvt   / tty4
  2848                              <1> 	;       ccvt   / tty5
  2849                              <1> 	;       ccvt   / tty6
  2850                              <1> 	;       ccvt   / tty7
  2851                              <1> 	;/       ejec / lpr
  2852                              <1> 
  2853                              <1> ctty: ; / close console tty
  2854                              <1> 	; 25/02/2022
  2855                              <1> 	; 12/02/2022
  2856                              <1> 	; 05/02/2022
  2857                              <1> 	; 04/02/2022
  2858                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2859                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2860                              <1> 	;
  2861                              <1> 	; Retro UNIX 8086 v1 modification !
  2862                              <1> 	; (DL = 2 -> it is open for reading)
  2863                              <1> 	; (DL = 1 -> it is open for writing)
  2864                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2865                              <1> 	;
  2866                              <1> 	; 06/12/2013
  2867 00005B17 0FB61D[416F0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2868 00005B1E 8A83[556C0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2869                              <1> 	; 13/01/2014
  2870                              <1> 	;jmp	short cttyp
  2871                              <1> 	; 05/02/2022
  2872 00005B24 EB04                <1> 	jmp	short ctty_0
  2873                              <1> ccvt:
  2874 00005B26 2C0A                <1> 	sub 	al, 10
  2875                              <1> cttyp:
  2876                              <1> 	; 08/01/2022
  2877 00005B28 31DB                <1> 	xor	ebx, ebx
  2878                              <1> ctty_0:	
  2879                              <1> 	; 18/05/2015 (32 bit modifications)
  2880                              <1> 	; 16/08/2013 - 26/01/2014
  2881                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  2882                              <1> 	; 04/02/2022
  2883 00005B2A 88C3                <1> 	mov	bl, al
  2884 00005B2C D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  2885                              <1> 	; 26/01/2014
  2886 00005B2E 81C3[946B0000]      <1> 	add 	ebx, ttyl
  2887 00005B34 88C6                <1> 	mov 	dh, al ; tty number
  2888 00005B36 668B03              <1> 	mov 	ax, [ebx]
  2889                              <1> 		   ; AL = lock value (0 or process number)
  2890                              <1> 		   ; AH = open count 
  2891 00005B39 20E4                <1> 	and 	ah, ah
  2892 00005B3B 7514                <1> 	jnz	short ctty_ret
  2893                              <1>   	; 12/02/2022
  2894 00005B3D 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  2895 00005B40 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  2896                              <1> 	; iclose (dl=1 or dl=2)
  2897 00005B42 C705[476F0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  2897 00005B4A 0000                <1>
  2898                              <1> 			; device not open ! error
  2899                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  2900 00005B4C E9D2DFFFFF          <1> 	jmp	error
  2901                              <1> 	; 26/01/2014
  2902                              <1> ctty_ret:
  2903 00005B51 FECC                <1> 	dec 	ah ; decrease open count
  2904 00005B53 7502                <1> 	jnz	short ctty_1
  2905 00005B55 30C0                <1> 	xor	al, al ; unlock/free tty
  2906                              <1> ctty_1:
  2907 00005B57 668903              <1> 	mov 	[ebx], ax ; close tty instance
  2908                              <1> 	;
  2909 00005B5A BB[286F0000]        <1> 	mov	ebx, u.ttyp
  2910                              <1> 	;test	dl, 1 ; open for write sign
  2911                              <1> 	;jz	short ctty_2
  2912                              <1> 	; 25/02/2022
  2913 00005B5F F6C202              <1> 	test	dl, 2 ; open for read sign
  2914 00005B62 7501                <1> 	jnz	short ctty_2
  2915 00005B64 43                  <1> 	inc	ebx
  2916                              <1> ctty_2:
  2917 00005B65 FEC6                <1> 	inc	dh ; tty number + 1
  2918 00005B67 3A33                <1> 	cmp	dh, [ebx]
  2919                              <1> 	;jne	short cret
  2920 00005B69 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  2921                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  2922 00005B6B C60300              <1> 	mov	byte [ebx], 0
  2923                              <1> ctty_3:
  2924                              <1> 	; 12/02/2022
  2925 00005B6E 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2926 00005B70 7401                <1> 	jz	short ctty_4
  2927                              <1> cret:
  2928                              <1> 	;pop	ax
  2929                              <1> 	; 05/02/2022
  2930 00005B72 58                  <1> 	pop	eax
  2931                              <1> ctty_stc_retn:	; 12/02/2022
  2932                              <1> ctty_4:
  2933 00005B73 C3                  <1> 	retn
  2934                              <1> 
  2935                              <1> ;ctty_err: ; 13/01/2014
  2936                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  2937                              <1> ;	jnz	error
  2938                              <1> ;	stc
  2939                              <1> ;	retn
  2940                              <1> 
  2941                              <1> 	; Original UNIX v1 'ctty' routine:
  2942                              <1> 	;	
  2943                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  2944                              <1> 	;		;/ point r5 to the console tty buffer
  2945                              <1>         ;decb   (r5) / dec number of processes using console tty
  2946                              <1>         ;br     sret / return via sret
  2947                              <1> 
  2948                              <1> ;ccvt:	; < close tty >
  2949                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2950                              <1> 	;
  2951                              <1> 	; Retro UNIX 8086 v1 modification !
  2952                              <1> 	; 
  2953                              <1> 	; In original UNIX v1, 'ccvt' routine 
  2954                              <1> 	;		(exactly different than this one)
  2955                              <1> 	;	was in 'u9.s' file.
  2956                              <1> 	;
  2957                              <1> 	; DL = 2 -> it is open for reading
  2958                              <1> 	; DL = 1 -> it is open for writing
  2959                              <1> 	;
  2960                              <1> 	; 17/09/2013
  2961                              <1> 	;sub 	al, 10
  2962                              <1> 	;cmp	al, 7
  2963                              <1> 	;jna	short cttyp
  2964                              <1> 	; 13/01/2014
  2965                              <1> 	;jmp	short cttyp
  2966                              <1> 
  2967                              <1> ;cppt: / close paper tape
  2968                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  2969                              <1> ;1:
  2970                              <1> ;        mov    $240,*$ps /set process or priority to 5
  2971                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  2972                              <1> ;                          / and assign to free list
  2973                              <1> ;               br sret
  2974                              <1> ;        br     1b
  2975                              <1> 
  2976                              <1> ;ejec:	
  2977                              <1> ;	jmp	error
  2978                              <1> ;/ejec:
  2979                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  2980                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  2981                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  2982                              <1> ;/       br     sret / return to caller via 'sret'
  1996                                  %include 'u8.s'        ; 11/06/2015
  1997                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  1998                              <1> ; Last Modification: 12/02/2022
  1999                              <1> ; ----------------------------------------------------------------------------
  2000                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2001                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2002                              <1> ;
  2003                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2004                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2005                              <1> ; <Bell Laboratories (17/3/1972)>
  2006                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2007                              <1> ;
  2008                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2009                              <1> ;
  2010                              <1> ; ****************************************************************************
  2011                              <1> ; 24/10/2015
  2012                              <1> 
  2013                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2014                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2015                              <1> ;; Word 1, byte 0 = device id
  2016                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2017                              <1> ;;          bit 9 = write bit
  2018                              <1> ;;	    bit 10 = read bit	  
  2019                              <1> ;;	    bit 12 = waiting to write bit	
  2020                              <1> ;;	    bit 13 = waiting to read bit
  2021                              <1> ;;	    bit 15 = inhibit bit
  2022                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2023                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2024                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2025                              <1> ;;
  2026                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2027                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2028                              <1> ;;
  2029                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2030                              <1> ;; Word 1, Byte 0 = device id
  2031                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2032                              <1> ;;          bit 9 = write bit
  2033                              <1> ;;	    bit 10 = read bit	  
  2034                              <1> ;;	    bit 12 = waiting to write bit	
  2035                              <1> ;;	    bit 13 = waiting to read bit
  2036                              <1> ;;	    bit 15 = inhibit bit
  2037                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2038                              <1> ;;
  2039                              <1> ;; Original UNIX v1 ->
  2040                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2041                              <1> ;; Original UNIX v1 -> 
  2042                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2043                              <1> ;;
  2044                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2045                              <1> ;;
  2046                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2047                              <1> ;;          0 = fd0
  2048                              <1> ;;	    1 = fd1
  2049                              <1> ;;	    2 = hd0
  2050                              <1> ;;	    3 = hd1
  2051                              <1> ;;	    4 = hd2
  2052                              <1> ;;	    5 = hd3
  2053                              <1> 
  2054                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2055                              <1> 
  2056                              <1> 	; 04/02/2022
  2057                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2058                              <1> 	; 26/04/2013
  2059                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2060                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2061                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2062                              <1> 
  2063                              <1> 	; 04/02/2022
  2064                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2065                              <1> 	; 26/04/2013
  2066                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2067                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2068                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2069                              <1> 
  2070                              <1> bread: 
  2071                              <1> 	; 12/02/2022
  2072                              <1> 	; 04/02/2022
  2073                              <1> 	; 14/07/2015
  2074                              <1> 	; 10/07/2015
  2075                              <1> 	; 09/06/2015
  2076                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2077                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2078                              <1> 	;	
  2079                              <1> 	; / read a block from a block structured device
  2080                              <1> 	;
  2081                              <1> 	; INPUTS ->
  2082                              <1> 	;    [u.fofp] points to the block number
  2083                              <1> 	;    CX = maximum block number allowed on device
  2084                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2085                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2086                              <1> 	;    [u.count]	number of bytes to read in
  2087                              <1> 	; OUTPUTS ->
  2088                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2089                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2090                              <1> 	;
  2091                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2092                              <1> 	;
  2093                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2094                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2095                              <1> 	;	is increased by 1. For example: If user/program request 
  2096                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2097                              <1> 	;  	the next block number just as 512 byte reading is done.
  2098                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2099                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2100                              <1> 	;       enough to keep byte position/offset of the disk), this
  2101                              <1> 	;	defect will not be corrected, user/program must request
  2102                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2103                              <1> 	;       for achieving correct result. In future version(s), 
  2104                              <1> 	;	this defect will be corrected by using different 
  2105                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2106                              <1> 
  2107                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2108                              <1> 			       ; / (only works on tape)
  2109                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2110                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2111                              <1> ;1:
  2112                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2113                              <1> 			    ; / maximum block # allowed on device
  2114                              <1> 		; jnb short @f
  2115                              <1> 		; bhis	1f / yes, 1f (error)
  2116                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2117                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2118                              <1> 		; mov (sp)+,r1 / return block # to r1
  2119                              <1> 		; inc r1 / bump block # to next consecutive block
  2120                              <1> 		; dec (sp) / "2-1-cold" on stack
  2121                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2122                              <1> ;1:
  2123                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2124                              <1> 	;push	ecx ; **
  2125                              <1> 	;26/04/2013
  2126                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2127 00005B74 2C03                <1> 	sub	al, 3
  2128                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2129 00005B76 A2[5A6F0000]        <1> 	mov	[u.brwdev], al
  2130                              <1> 	; 09/06/2015
  2131                              <1> 	;movzx	ebx, al
  2132                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2133                              <1> 	; 04/02/2022 (BugFix)
  2134 00005B7B C0E002              <1> 	shl	al, 2 ; * 4
  2135 00005B7E 8B88[6E660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2136                              <1> bread_0:
  2137 00005B84 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2138                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2139                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2140 00005B85 8B1D[086F0000]      <1> 	mov	ebx, [u.fofp]
  2141 00005B8B 8B03                <1> 	mov	eax, [ebx]
  2142 00005B8D C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2143                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2144                              <1> 			       ; / block #
  2145 00005B90 39C8                <1> 	cmp	eax, ecx
  2146                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2147                              <1>        	                     ; / block number allowed
  2148                              <1> 	;jnb	error 	     ; 18/04/2013
  2149                              <1> 		; bhis error10 / yes, error
  2150                              <1> 	; 12/02/2022
  2151                              <1> 	;jb	short bread_1
  2152                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2153                              <1> 	;jmp	error
  2154 00005B92 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2155                              <1> bread_1:
  2156                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2157                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2158                              <1> 	; eAX = Block number (zero based)
  2159                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2160                              <1> preread: ;; call preread
  2161 00005B94 BF[5A6F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2162 00005B99 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2163                              <1> 	;; jc 	error
  2164                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2165                              <1>         ; eAX = Block/Sector number (r1)
  2166                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2167                              <1> 	; 14/03/2013
  2168 00005B9E 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2169                              <1>        		; br 1f / branch if block already in a I/O buffer
  2170 00005BA0 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2171                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2172 00005BA5 E8DA010000          <1> 	call	poke
  2173                              <1>         	; jsr r0,poke / perform the read
  2174                              <1> 	;;jc	error ;2 0/07/2013
  2175                              <1> ; 1:
  2176                              <1>  		; clr *$ps / ps = 0
  2177                              <1>         	; rts r0
  2178                              <1> 	; 12/02/2022
  2179 00005BAA 7305                <1> 	jnc	short bread_2
  2180 00005BAC E937010000          <1> 	jmp	dskrd_err
  2181                              <1> 
  2182                              <1> ;; return from preread
  2183                              <1> bread_2:
  2184 00005BB1 66810B0040          <1> 	or	word [ebx], 4000h 
  2185                              <1> 		; bis $40000,(r5) 
  2186                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2187                              <1> bread_3: ; 1:
  2188 00005BB6 66F7030024          <1> 	test	word [ebx], 2400h
  2189                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2190 00005BBB 7407                <1> 	jz	short bread_4
  2191                              <1> 		; beq 1f / no
  2192                              <1> 		; cmp cdev,$1 / disk or drum?
  2193                              <1> 		; ble 2f / yes
  2194                              <1> 		; tstb uquant / is the time quantum = 0?
  2195                              <1> 		; bne 2f / no, 2f
  2196                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2197                              <1> 		; jsr r0,sleep; 31. 
  2198                              <1> 			; / put process to sleep in channel 31 (tape)
  2199                              <1> 		; mov (sp)+,r5 / restore r5
  2200                              <1> 		; br 1b / go back
  2201                              <1> ; 2: / drum or disk
  2202                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2203 00005BBD E8B5F3FFFF          <1> 	call	idle
  2204                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2205 00005BC2 EBF2                <1> 	jmp	short bread_3
  2206                              <1>        		; br 1b
  2207                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2208 00005BC4 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2209                              <1> 		; bic $40000,(r5) / clear bit 14
  2210                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2211 00005BC9 83C308              <1> 	add	ebx, 8
  2212                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2213                              <1> 	; 09/06/2015
  2214 00005BCC 66833D[576F0000]00  <1> 	cmp	word [u.pcount], 0
  2215 00005BD4 7705                <1> 	ja	short bread_5
  2216 00005BD6 E871F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2217                              <1> bread_5:
  2218                              <1> 	; eBX = system (I/O) buffer address
  2219 00005BDB E870000000          <1> 	call	dioreg
  2220                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2221                              <1> 	; esi = start address of the transfer (in the buffer)
  2222                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2223                              <1> 	; ecx = transfer count (in bytes)
  2224                              <1> 	;
  2225                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2226                              <1> ;   / of users data
  2227 00005BE0 F3A4                <1> 	rep	movsb
  2228                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2229                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2230                              <1>        		; bne 1b
  2231 00005BE2 59                  <1> 	pop	ecx ; **
  2232 00005BE3 833D[1C6F0000]00    <1> 	cmp	dword [u.count], 0
  2233                              <1> 		; tst u.count / done
  2234 00005BEA 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2235                              <1>        		; beq 1f / yes, return
  2236                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2237                              <1>        		; br bread / read some more
  2238                              <1> ; 1:
  2239 00005BEC 58                  <1> 	pop	eax ; ****
  2240                              <1>        		; mov (sp)+,r0
  2241 00005BED C3                  <1>         retn		; 09/06/2015
  2242                              <1> 	;jmp	ret_ 
  2243                              <1> 		;jmp ret / jump to routine that called readi
  2244                              <1> 
  2245                              <1> 	; 08/02/2022
  2246                              <1> brw_oov_err:
  2247 00005BEE C705[476F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2247 00005BF6 0000                <1>
  2248 00005BF8 E926DFFFFF          <1> 	jmp	error
  2249                              <1> 
  2250                              <1> 	; 12/02/2022
  2251                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2252                              <1> 	; 26/04/2013
  2253                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2254                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2255                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2256                              <1> 
  2257                              <1> 	; 12/02/2022				
  2258                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2259                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2260                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2261                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2262                              <1> 
  2263                              <1> bwrite: 
  2264                              <1> 	; 12/02/2022
  2265                              <1> 	; 04/02/2022
  2266                              <1> 	; 14/07/2015
  2267                              <1> 	; 10/07/2015
  2268                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2269                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2270                              <1> 	;	
  2271                              <1> 	;; / write on block structured device
  2272                              <1> 	;
  2273                              <1> 	; INPUTS ->
  2274                              <1> 	;    [u.fofp] points to the block number
  2275                              <1> 	;    CX = maximum block number allowed on device
  2276                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2277                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2278                              <1> 	;    [u.count]	number of bytes to user desires to write
  2279                              <1> 	; OUTPUTS ->
  2280                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2281                              <1> 	;
  2282                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2283                              <1> 	;
  2284                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2285                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2286                              <1> 	;	is increased by 1. For example: If user/program request 
  2287                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2288                              <1> 	;  	the next block number just as 512 byte writing is done.
  2289                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2290                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2291                              <1> 	;       enough to keep byte position/offset of the disk), this
  2292                              <1> 	;	defect will not be corrected, user/program must request
  2293                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2294                              <1> 	;       for achieving correct result. In future version(s), 
  2295                              <1> 	;	this defect will be corrected by using different 
  2296                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2297                              <1> 
  2298                              <1>        		; jsr r0,tstdeve / test the device for an error
  2299                              <1> 	;push	ecx ; **
  2300                              <1> 	;26/04/2013
  2301                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2302 00005BFD 2C03                <1> 	sub	al, 3
  2303                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2304 00005BFF A2[5A6F0000]        <1> 	mov	[u.brwdev], al
  2305                              <1> 	; 09/06/2015
  2306                              <1> 	;movzx	ebx, al
  2307                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2308                              <1> 	; 04/02/2022 (BugFix)
  2309 00005C04 C0E002              <1> 	shl	al, 2 ; * 4
  2310 00005C07 8B88[6E660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2311                              <1> bwrite_0:
  2312 00005C0D 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2313                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2314                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2315 00005C0E 8B1D[086F0000]      <1> 	mov	ebx, [u.fofp]
  2316 00005C14 8B03                <1> 	mov	eax, [ebx]       
  2317 00005C16 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2318                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2319 00005C19 39C8                <1> 	cmp	eax, ecx
  2320                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2321                              <1>        	                     ; / block number allowed
  2322                              <1> 	;jnb	error	     ; 18/04/2013
  2323                              <1> 		; bhis error10 / yes, error
  2324                              <1>      	; 12/02/2022
  2325                              <1> 	;jb	short bwrite_1
  2326                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2327                              <1> 	;jmp	error
  2328 00005C1B 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2329                              <1> bwrite_1:
  2330                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2331                              <1> 		; inc *u.fofp / no, increment block number
  2332                              <1> 	; 09/06/2015 - 10/07/2015
  2333 00005C1D 66833D[576F0000]00  <1> 	cmp	word [u.pcount], 0
  2334 00005C25 7705                <1> 	ja	short bwrite_2
  2335 00005C27 E81CF9FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2336                              <1> bwrite_2:
  2337 00005C2C BF[5A6F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2338 00005C31 E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2339                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2340                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2341 00005C36 E815000000          <1>         call	dioreg
  2342                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2343                              <1> 	; esi =  destination address (in the buffer)
  2344                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2345                              <1> 	; ecx =  transfer count (in bytes)
  2346                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2347 00005C3B 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2348 00005C3D F3A4                <1> 	rep	movsb
  2349                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2350                              <1>        		; dec r3 / area to the I/O buffer
  2351                              <1>        		; bne 1b
  2352 00005C3F E80D010000          <1> 	call	dskwr
  2353                              <1> 		; jsr r0,dskwr / write it out on the device
  2354 00005C44 59                  <1> 	pop	ecx ; **
  2355 00005C45 833D[1C6F0000]00    <1>         cmp     dword [u.count], 0
  2356                              <1> 		; tst u.count / done
  2357 00005C4C 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2358                              <1> 		; beq 1f / yes, 1f
  2359                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2360                              <1>        		; br bwrite / go back and write next block
  2361                              <1> ; 1:
  2362 00005C4E 58                  <1> 	pop	eax ; ****
  2363                              <1>        		; mov (sp)+,r0
  2364 00005C4F C3                  <1> 	retn		; 09/06/2015
  2365                              <1>         ;jmp	ret_ 
  2366                              <1> 		; jmp ret / return to routine that called writei
  2367                              <1> ;error10:
  2368                              <1> ;       jmp     error  ; / see 'error' routine
  2369                              <1> 
  2370                              <1> dioreg:
  2371                              <1> 	; 04/02/2022
  2372                              <1> 	; 14/07/2015
  2373                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2374                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2375                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2376                              <1> 	;	
  2377                              <1> 	; bookkeeping on block transfers of data
  2378                              <1> 	;
  2379                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2380                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2381                              <1> 	; 10/07/2015
  2382                              <1> 	; * returns byte offset from beginning of current sector buffer
  2383                              <1> 	; (beginning of data) in ESI
  2384                              <1> 	;
  2385 00005C50 8B0D[1C6F0000]      <1> 	mov	ecx, [u.count]
  2386                              <1> 		; mov u.count,r3 / move char count to r3
  2387                              <1>         ; 04/02/2022
  2388 00005C56 31D2                <1> 	xor	edx, edx
  2389 00005C58 B602                <1> 	mov	dh, 2
  2390                              <1> 	; edx = 512
  2391 00005C5A 39D1                <1> 	cmp	ecx, edx ; 512
  2392                              <1> 	;cmp 	ecx, 512
  2393                              <1> 		; cmp r3,$512. / more than 512. char?
  2394 00005C5C 7602                <1> 	jna	short dioreg_0
  2395                              <1> 		; blos 1f / no, branch
  2396 00005C5E 89D1                <1> 	mov	ecx, edx ; 512
  2397                              <1> 	;mov	ecx, 512
  2398                              <1> 		; mov $512.,r3 / yes, just take 512.
  2399                              <1> dioreg_0:
  2400                              <1> 	; 09/06/2015
  2401 00005C60 663B0D[576F0000]    <1> 	cmp	cx, [u.pcount]
  2402 00005C67 7607                <1> 	jna	short dioreg_1
  2403 00005C69 668B0D[576F0000]    <1> 	mov	cx, [u.pcount]
  2404                              <1> dioreg_1:
  2405                              <1> ; 1:
  2406 00005C70 8B15[186F0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2407                              <1> 	        ; mov u.base,r2 / put users base in r2
  2408 00005C76 010D[206F0000]      <1> 	add	[u.nread], ecx
  2409                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2410 00005C7C 290D[1C6F0000]      <1> 	sub	[u.count], ecx
  2411                              <1> 		; sub r3,u.count / update count
  2412 00005C82 010D[186F0000]      <1> 	add	[u.base], ecx
  2413                              <1> 		; add r3,u.base / update base
  2414                              <1> 	; 10/07/2015
  2415                              <1> 	; Retro UNIX 386 v1 - modification !
  2416                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2417                              <1> 	; (It will point to next byte position instead of next block no.)
  2418 00005C88 8B35[086F0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2419 00005C8E 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2420 00005C90 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2421 00005C92 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2422 00005C97 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2423 00005C99 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2424                              <1> 	; 09/06/2015 - 10/07/2015
  2425 00005C9B 66290D[576F0000]    <1> 	sub	[u.pcount], cx
  2426 00005CA2 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2427 00005CA8 8B3D[536F0000]      <1> 	mov	edi, [u.pbase]
  2428 00005CAE 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2429 00005CB4 01D7                <1> 	add	edi, edx
  2430 00005CB6 893D[536F0000]      <1> 	mov	[u.pbase], edi
  2431 00005CBC 010D[536F0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2432 00005CC2 C3                  <1> 	retn
  2433                              <1> 		; rts r0 / return
  2434                              <1> 
  2435                              <1> dskrd:
  2436                              <1> 	; 12/02/2022
  2437                              <1> 	; 18/08/2015
  2438                              <1> 	; 02/07/2015
  2439                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2440                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2441                              <1> 	;
  2442                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2443                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2444                              <1> 	; (number specified in r1) in the acquired buffer.
  2445                              <1> 	; If the device is busy at the time dskrd is called,	
  2446                              <1> 	; dskrd calls idle.
  2447                              <1> 	; 
  2448                              <1> 	; INPUTS ->
  2449                              <1> 	;    r1 - block number
  2450                              <1> 	;    cdev - current device number 
  2451                              <1> 	; OUTPUTS ->
  2452                              <1> 	;    r5 - points to first data word in I/O buffer
  2453                              <1> 	;
  2454                              <1> 	; ((AX = R1)) input/output
  2455                              <1> 	; ((BX = R5)) output 
  2456                              <1> 	;
  2457                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2458                              <1> 	;
  2459 00005CC3 E851010000          <1> 	call 	bufaloc
  2460                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2461                              <1> 			       ; / get a free I/O buffer
  2462                              <1> 	;;jc	error ; 20/07/2013
  2463 00005CC8 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2464                              <1>        		; br 1f / branch if block already in a I/O buffer
  2465                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2466 00005CCA 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2467                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2468                              <1> 		               ; / I/O queue entry for buffer
  2469 00005CCF E8B0000000          <1> 	call	poke
  2470                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2471                              <1> 			    ; /	bit 10=1 says read
  2472                              <1> 	; 09/06/2015
  2473                              <1> 	;jnc	short dskrd_1
  2474                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2475                              <1> 	;jmp	error
  2476                              <1> 	; 08/02/2022
  2477 00005CD4 7212                <1> 	jc	short dskrd_3
  2478                              <1> dskrd_1: ; 1:
  2479                              <1>        		;clr *$ps
  2480 00005CD6 66F7030024          <1>        	test	word [ebx], 2400h
  2481                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2482                              <1> 				; / jump to idle
  2483 00005CDB 7407                <1>        	jz	short dskrd_2
  2484                              <1> 		; beq 1f
  2485                              <1>         ;;mov   ecx, [s.wait_]
  2486 00005CDD E895F2FFFF          <1>        	call	idle
  2487                              <1> 		; jsr r0,idle; s.wait+2
  2488 00005CE2 EBF2                <1> 	jmp 	short dskrd_1
  2489                              <1>        		; br 1b
  2490                              <1> dskrd_2: ; 1:
  2491 00005CE4 83C308              <1>         add	ebx, 8
  2492                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2493                              <1> 			  ; / just read in
  2494 00005CE7 C3                  <1>        	retn
  2495                              <1> 		; rts r0
  2496                              <1> dskrd_err: 
  2497                              <1> 	; 08/02/2022
  2498                              <1> 	; (jump from 'bread' error)
  2499                              <1> dskrd_3:	
  2500                              <1> 	; 08/02/2022
  2501 00005CE8 803D[5A6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2502 00005CEF 7509                <1> 	jne	short dskrd_4 ; no
  2503                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2504 00005CF1 C605[5A6F0000]00    <1> 	mov	byte [u.brwdev], 0
  2505 00005CF8 EB0A                <1> 	jmp	short dskrd_5
  2506                              <1> dskrd_4:
  2507 00005CFA C705[476F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2507 00005D02 0000                <1>
  2508                              <1> dskrd_5:
  2509 00005D04 E91ADEFFFF          <1> 	jmp	error
  2510                              <1> 
  2511                              <1> bwslot:
  2512                              <1> 	; 04/02/2022
  2513                              <1> 	; 10/07/2015
  2514                              <1> 	;	If the block/sector is not placed in a buffer
  2515                              <1> 	;	before 'wslot', it must be read before
  2516                              <1> 	;	it is written! (Otherwise transfer counts less
  2517                              <1> 	;	than 512 bytes will be able to destroy existing 
  2518                              <1> 	;	data on disk.)
  2519                              <1> 	;
  2520                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2521                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2522                              <1> 	; Retro UNIX 8086 v1 modification !
  2523                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2524                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2525                              <1> 	;	-> eAX = block number
  2526                              <1> 	;
  2527 00005D09 E818010000          <1> 	call	bufaloc_0
  2528 00005D0E 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2529                              <1> 	; 04/02/2022
  2530                              <1> 	; ebx = buffer header address
  2531                              <1> bwslot_0:
  2532                              <1> 	; 10/07/2015
  2533 00005D10 8B35[086F0000]      <1> 	mov	esi, [u.fofp]
  2534 00005D16 8B06                <1> 	mov	eax, [esi]
  2535 00005D18 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2536 00005D1D 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2537                              <1> 		       ; recent disk data must be placed in the buffer
  2538 00005D1F 813D[1C6F0000]0002- <1> 	cmp	dword [u.count], 512
  2538 00005D27 0000                <1>
  2539 00005D29 730F                <1> 	jnb	short wslot_0	
  2540                              <1> bwslot_1:
  2541 00005D2B E89AFFFFFF          <1> 	call	dskrd_0
  2542                              <1> 	; 04/02/2022
  2543                              <1> 	; ebx = buffer data address = buffer header address + 8
  2544 00005D30 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2545 00005D33 EB05                <1> 	jmp 	short wslot_0
  2546                              <1> 
  2547                              <1> wslot:
  2548                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2549                              <1> 	; 		(32 bit modifications)
  2550                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2551                              <1> 	;
  2552                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2553                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2554                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2555                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2556                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2557                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2558                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2559                              <1> 	;
  2560                              <1> 	; INPUTS ->
  2561                              <1>  	;    r1 - block number
  2562                              <1> 	;    cdev - current (block/disk) device number
  2563                              <1>  	;
  2564                              <1> 	; OUTPUTS ->
  2565                              <1> 	;    bufp - bits 9 and 15 are set, 
  2566                              <1> 	;           the remainder of the word left unchanged
  2567                              <1> 	;    r5 - points to first data word in I/O buffer
  2568                              <1> 	;
  2569                              <1> 	; ((AX = R1)) input/output
  2570                              <1> 	; ((BX = R5)) output 
  2571                              <1> 	;
  2572                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2573                              <1> 
  2574 00005D35 E8DF000000          <1> 	call	bufaloc
  2575                              <1> 	; 10/07/2015
  2576                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2577                              <1>         	; br 1f / word in buffer in r5
  2578                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2579                              <1>         ; eAX = Block/Sector number (r1)
  2580                              <1> wslot_0: ;1:
  2581 00005D3A 66F7030024          <1>      	test	word [ebx], 2400h
  2582                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2583                              <1> 				; / of I/O queue entry
  2584 00005D3F 7407                <1> 	jz	short wslot_1
  2585                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2586                              <1> 		        ; / or not waiting to read)
  2587                              <1> 
  2588                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2589 00005D41 E831F2FFFF          <1> 	call	idle
  2590                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2591                              <1>        	                     ; / idle
  2592 00005D46 EBF2                <1> 	jmp	short wslot_0
  2593                              <1> 		; br 1b / till finished
  2594                              <1> wslot_1: ;1:
  2595 00005D48 66810B0082          <1> 	or      word [ebx], 8200h
  2596                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2597                              <1>                             	 ; / (write, inhibit bits)
  2598                              <1>        		; clr *$ps / clear processor status
  2599 00005D4D 83C308              <1> 	add	ebx, 8 ; 11/06/2015
  2600                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2601                              <1> 			  ; / for this block
  2602                              <1> dskwr_1:	; 08/02/2022
  2603 00005D50 C3                  <1> 	retn
  2604                              <1> 		; rts r0
  2605                              <1> dskwr:
  2606                              <1> 	; 12/02/2022
  2607                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2608                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2609                              <1> 	;
  2610                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2611                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2612                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2613                              <1> 	; previously has supplied all the information required in the
  2614                              <1> 	; I/O queue entry.
  2615                              <1> 	;
  2616                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2617                              <1> 	;
  2618                              <1> 	;
  2619 00005D51 8B1D[BA6E0000]      <1> 	mov	ebx, [bufp]
  2620 00005D57 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2621                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2622                              <1>                                   ; / bottom of queue
  2623 00005D5C E823000000          <1> 	call	poke
  2624                              <1> 	; 09/06/2015
  2625 00005D61 73ED                <1> 	jnc	short dskwr_1
  2626                              <1> 	; 12/02/2022
  2627 00005D63 803D[5A6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2628 00005D6A 7509                <1> 	jne	short dskwr_0 ; no
  2629                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2630 00005D6C C605[5A6F0000]00    <1> 	mov	byte [u.brwdev], 0
  2631 00005D73 EB0A                <1> 	jmp	short dskwr_2
  2632                              <1> dskwr_0:
  2633 00005D75 C705[476F0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2633 00005D7D 0000                <1>
  2634                              <1> dskwr_2:
  2635 00005D7F E99FDDFFFF          <1> 	jmp	error
  2636                              <1> ;dskwr_1:
  2637                              <1> ;	retn
  2638                              <1> 
  2639                              <1> ;ppoke:
  2640                              <1>        		; mov $340,*$ps
  2641                              <1>        		; jsr r0,poke
  2642                              <1>        		; clr *$ps
  2643                              <1> 		; rts r0
  2644                              <1> poke:
  2645                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2646                              <1> 	; 24/10/2015
  2647                              <1> 	; 20/08/2015
  2648                              <1> 	; 18/08/2015
  2649                              <1> 	; 02/07/2015
  2650                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2651                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2652                              <1> 	;
  2653                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2654                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2655                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2656                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2657                              <1> 	;
  2658                              <1> 	; Basic I/O functions for all block structured devices
  2659                              <1> 	;
  2660                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2661                              <1> 	;
  2662                              <1> 	; 20/07/2013 modifications
  2663                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2664                              <1> 	; INPUTS -> 
  2665                              <1> 	;        (EBX = buffer header address)
  2666                              <1> 	; OUTPUTS ->
  2667                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2668                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2669                              <1> 	;		(drive not ready or r/w error!)
  2670                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2671                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2672                              <1> 	;        (also it indicates invalid buffer data)
  2673                              <1> 	;
  2674 00005D84 53                  <1> 	push	ebx
  2675                              <1>        		; mov r1,-(sp)
  2676                              <1>        		; mov r2,-(sp)
  2677                              <1>        		; mov r3,-(sp)
  2678 00005D85 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2679                              <1> 	;
  2680                              <1> 	; 09/06/2015
  2681                              <1> 	; (permit read/write after a disk R/W error)
  2682 00005D86 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2683 00005D88 B001                <1> 	mov	al, 1
  2684 00005D8A D2E0                <1> 	shl	al, cl
  2685 00005D8C 8405[E26E0000]      <1> 	test 	al, [active] ; busy ? (error)
  2686 00005D92 7408                <1> 	jz	short poke_0
  2687 00005D94 F6D0                <1> 	not	al
  2688 00005D96 2005[E26E0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2689                              <1> poke_0:
  2690 00005D9C BE[DA6E0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2691                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2692                              <1> 					 ; / I/O queue pointer
  2693                              <1> poke_1: ; 1:
  2694 00005DA1 83EE04              <1>         sub	esi, 4
  2695 00005DA4 8B1E                <1> 	mov	ebx, [esi]
  2696                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2697 00005DA6 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2698 00005DA9 F6C406              <1>        	test	ah, 06h
  2699                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2700                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2701                              <1> 			       ; / queue entry
  2702 00005DAC 745C                <1>         jz      short poke_5
  2703                              <1> 		; beq 2f / branch to 2f if both are clear
  2704                              <1> 	; 31/07/2013
  2705                              <1> 	;test	ah, 0B0h ; (*)
  2706                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2707                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2708                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2709                              <1> 		; bne 2f / branch if any are set
  2710                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2711                              <1>     		; movb (r1),r3 / get device id
  2712 00005DAE 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2713                              <1> 	;mov	edi, ecx ; 26/04/2013
  2714 00005DB1 31C0                <1> 	xor 	eax, eax ; 0
  2715                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2716                              <1> 		; tstb deverr(r3) / test for errors on this device
  2717                              <1>        	;jna	short poke_2 
  2718                              <1> 		; beq 3f / branch if no errors
  2719                              <1> 	; 02/07/2015
  2720                              <1> 	;dec	eax
  2721                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2722                              <1>        		; mov $-1,2(r1) / destroy associativity
  2723                              <1> 	;shr	eax, 24
  2724                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2725                              <1> 		; clrb 1(r1) / do not do I/O
  2726                              <1> 	;jmp     short poke_5
  2727                              <1>         ;       ; br 2f
  2728                              <1>                 ; rts r0
  2729                              <1> poke_2: ; 3:
  2730                              <1> 	; 02/07/2015
  2731 00005DB3 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2732 00005DB5 7453                <1> 	jz	short poke_5
  2733 00005DB7 FEC0                <1> 	inc	al ; mov ax, 1
  2734 00005DB9 FEC9                <1> 	dec	cl
  2735 00005DBB 7402                <1> 	jz	short poke_3
  2736                              <1> 	; 26/04/2013 Modification
  2737                              <1> 	;inc	al ; mov ax, 1
  2738                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2739                              <1> 	;jz	short poke_3 ; cl = 0
  2740 00005DBD D2E0                <1> 	shl	al, cl ; shl ax, cl
  2741                              <1> poke_3:
  2742                              <1> 	;test	[active], ax
  2743 00005DBF 8405[E26E0000]      <1> 	test	[active], al
  2744                              <1> 		; bit $2,active / test disk busy bit
  2745 00005DC5 7543                <1> 	jnz     short poke_5
  2746                              <1> 		; bne 2f / branch if bit is set
  2747                              <1> 	;or	[active], ax
  2748 00005DC7 0805[E26E0000]      <1> 	or	[active], al
  2749                              <1> 		; bis $2,active / set disk busy bit
  2750                              <1> 	;push	ax
  2751                              <1> 	; 04/02/2022
  2752 00005DCD 50                  <1> 	push	eax
  2753 00005DCE E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2754                              <1> 	;mov    [edi+drv.error], ah
  2755                              <1> 	; 04/02/2022
  2756 00005DD3 58                  <1> 	pop	eax
  2757                              <1> 	;pop	ax
  2758 00005DD4 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2759                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2760                              <1> 	;jna	short poke_4
  2761                              <1> 		; tstb deverr(r3) / test for errors on this device
  2762                              <1>        		; beq 3f / branch if no errors
  2763                              <1> 	; 02/07/2015 (32 bit modification)
  2764                              <1> 	; 20/07/2013
  2765 00005DD6 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2766                              <1>        		; mov $-1,2(r1) / destroy associativity
  2767 00005DDD 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2768                              <1> 		; clrb 1(r1) / do not do I/O
  2769 00005DE2 EB26                <1> 	jmp     short poke_5
  2770                              <1> poke_4:	; 20/07/2013
  2771                              <1> 	; 17/07/2013
  2772 00005DE4 F6D0                <1> 	not 	al 
  2773 00005DE6 2005[E26E0000]      <1> 	and	[active], al ; reset, not busy
  2774                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2775                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2776 00005DEC 668B03              <1> 	mov	ax, [ebx]
  2777                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2778 00005DEF 66250006            <1>         and	ax, 600h
  2779                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2780 00005DF3 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2781                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2782 00005DF8 C0E403              <1> 	shl	ah, 3
  2783                              <1>        		; rol r3
  2784                              <1>                 ; rol r3
  2785                              <1>                 ; rol r3	
  2786 00005DFB 660903              <1> 	or	[ebx], ax
  2787                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2788                              <1> 			   ; bits 12 and 13
  2789 00005DFE E874F1FFFF          <1> 	call	idle ; 18/01/2014
  2790                              <1> 	;; sti
  2791                              <1> 	;hlt 	; wait for a hardware interrupt
  2792                              <1> 	;; cli
  2793                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2794                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2795                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2796                              <1> 	; method, this procedure will wait for a time according to
  2797                              <1> 	; multi tasking and time sharing concept.
  2798                              <1> 	;
  2799                              <1> 	; 24/10/2015
  2800                              <1> 	;not	ax 
  2801 00005E03 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2802 00005E07 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2803                              <1> poke_5: ;2:
  2804 00005E0A 81FE[BA6E0000]      <1>         cmp     esi, bufp
  2805                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2806                              <1>                             ; / has been scanned
  2807 00005E10 778F                <1> 	ja      short poke_1
  2808                              <1>                ; bhi 1b
  2809                              <1> 	; 24/03/2013
  2810                              <1>        		; mov (sp)+,r3
  2811                              <1>        		; mov (sp)+,r2
  2812                              <1>        		; mov (sp)+,r1
  2813 00005E12 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2814 00005E13 5B                  <1> 	pop 	ebx
  2815                              <1> 	; 02/07/2015 (32 bit modification)
  2816                              <1> 	; 20/07/2013
  2817                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2818 00005E14 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2819                              <1> 	;	
  2820                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2821                              <1> 	; or written succesfully; even if an error occurs while
  2822                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2823                              <1> 	;
  2824                              <1> 	; 09/06/2015
  2825 00005E17 F5                  <1> 	cmc
  2826 00005E18 C3                  <1> 	retn
  2827                              <1>                 ; rts r0
  2828                              <1> 
  2829                              <1> bufaloc:
  2830                              <1> 	; 04/02/2022
  2831                              <1> 	; 20/08/2015
  2832                              <1> 	; 19/08/2015
  2833                              <1> 	; 02/07/2015
  2834                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2835                              <1> 	;	     (32 bit modifications)	
  2836                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2837                              <1> 	;
  2838                              <1> 	; bufaloc - Block device I/O buffer allocation
  2839                              <1> 	; 
  2840                              <1> 	; INPUTS ->
  2841                              <1> 	;    r1 - block number
  2842                              <1> 	;    cdev - current (block/disk) device number
  2843                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2844                              <1> 	; OUTPUTS ->
  2845                              <1> 	;    r5 - pointer to buffer allocated
  2846                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2847                              <1> 	;
  2848                              <1> 	; ((AX = R1)) input/output
  2849                              <1> 	; ((BX = R5)) output
  2850                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2851                              <1> 	;    zf=1 -> block already in a I/O buffer
  2852                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2853                              <1> 	;    ((DL = Device ID))
  2854                              <1> 	;    (((DH = 0 or 1)))
  2855                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2856                              <1> 	;    ((CX and DH will not be used after return)))
  2857                              <1> 
  2858                              <1> 	;;push 	esi ; ***
  2859                              <1> 		; mov r2,-(sp) / save r2 on stack
  2860                              <1>        		; mov $340,*$ps / set processor priority to 7
  2861                              <1> 		; 20/07/2013
  2862                              <1> 	; 26/04/2013
  2863                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2864                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  2865                              <1> 	;add	edi, ebx
  2866                              <1> 	; 09/01/2022
  2867 00005E19 0FB63D[DE6E0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2868 00005E20 81C7[E06E0000]      <1> 	add	edi, rdev
  2869                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2870                              <1> 			;; eDI points to device id.
  2871 00005E26 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2872                              <1> 	; 11/06/2015
  2873 00005E29 80BB[8A660000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2874 00005E30 720F                <1> 	jb	short bufaloc_9
  2875 00005E32 C705[476F0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2875 00005E3A 0000                <1>
  2876 00005E3C E9E2DCFFFF          <1> 	jmp	error
  2877                              <1> bufaloc_9:
  2878 00005E41 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2879                              <1> bufaloc_10: ; 02/07/2015
  2880 00005E43 31ED                <1> 	xor 	ebp, ebp ; 0
  2881 00005E45 55                  <1> 	push	ebp ; 0
  2882 00005E46 89E5                <1>         mov     ebp, esp	
  2883                              <1> 	;
  2884                              <1> bufaloc_1: ;1:
  2885                              <1> 		; clr -(sp) / vacant buffer
  2886 00005E48 BE[BA6E0000]        <1>         mov 	esi, bufp
  2887                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2888                              <1> 			     ; / entrys in buffer area
  2889                              <1> bufaloc_2: ;2:
  2890 00005E4D 8B1E                <1> 	mov	ebx, [esi]
  2891                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2892                              <1> 			    ; queue entry into r5
  2893 00005E4F 66F70300F6          <1> 	test	word [ebx], 0F600h
  2894                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2895 00005E54 7503                <1>         jnz	short bufaloc_3
  2896                              <1> 		; bne 3f / branch when 
  2897                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2898                              <1>                        ; / (i.e., buffer busy)
  2899 00005E56 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2900                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2901                              <1> 			; / found points to word 2 of I/O queue entry)
  2902                              <1> bufaloc_3: ;3:
  2903                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2904                              <1> 	;
  2905 00005E59 3813                <1> 	cmp	[ebx], dl	
  2906                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2907                              <1> 			       ; / as current device
  2908 00005E5B 7508                <1> 	jne	short bufaloc_4
  2909                              <1>        		; bne 3f
  2910 00005E5D 394304              <1> 	cmp	[ebx+4], eax
  2911                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2912                              <1> 			     ; / same as current block number
  2913 00005E60 7503                <1>        	jne	short bufaloc_4
  2914                              <1> 		; bne 3f
  2915                              <1> 	;add	esp, 4
  2916 00005E62 59                  <1> 	pop	ecx
  2917                              <1>        		; tst (sp)+ / bump stack pointer
  2918 00005E63 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2919                              <1> 				; jump to bufaloc_6 in original Unix v1
  2920                              <1>        		; br 1f / use this buffer
  2921                              <1> bufaloc_4: ;3:
  2922 00005E65 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2923                              <1> 	;
  2924 00005E68 81FE[D26E0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2925                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2926 00005E6E 72DD                <1> 	jb	short bufaloc_2
  2927                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2928                              <1>                        ; / buffers not checked)
  2929 00005E70 5E                  <1>         pop	esi
  2930                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2931                              <1> 			     ; / to last free block
  2932 00005E71 09F6                <1>        	or	esi, esi 
  2933 00005E73 7507                <1> 	jnz	short bufaloc_5
  2934                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2935                              <1> 	        ; / if a free buffer is found branch to 2f
  2936                              <1>         ;; mov  ecx, [s.wait_]
  2937 00005E75 E8FDF0FFFF          <1> 	call	idle
  2938                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2939 00005E7A EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2940                              <1>        		; br 1b
  2941                              <1> bufaloc_5: ;2:
  2942                              <1> 		; tst (r0)+ / skip if warmed over buffer
  2943 00005E7C FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  2944                              <1> bufaloc_6: ;1:
  2945 00005E7E 8B1E                <1>         mov    	ebx, [esi] 
  2946                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  2947                              <1> 			     ; / entry in r5
  2948                              <1> 	;; 26/04/2013
  2949                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  2950 00005E80 8813                <1> 	mov 	[ebx], dl
  2951                              <1> 		; movb cdev,(r5) / put current device number 
  2952                              <1> 				 ; / in I/O queue entry
  2953 00005E82 894304              <1> 	mov 	[ebx+4], eax
  2954                              <1> 		; mov r1,2(r5) / move block number into word 2 
  2955                              <1> 			     ; / of I/O queue entry
  2956                              <1> bufaloc_7: ;1:
  2957 00005E85 81FE[BA6E0000]      <1>         cmp	esi, bufp
  2958                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  2959                              <1> 			     ; / and put latest assigned
  2960 00005E8B 760A                <1> 	jna	short bufaloc_8	
  2961                              <1>        		; blos 1f / buffer on the top 
  2962                              <1> 			; / (this makes if the lowest priority)
  2963 00005E8D 83EE04              <1> 	sub	esi, 4
  2964 00005E90 8B0E                <1> 	mov	ecx, [esi]
  2965 00005E92 894E04              <1> 	mov	[esi+4], ecx
  2966                              <1> 		; mov -(r2),2(r2) / job for a particular device
  2967 00005E95 EBEE                <1> 	jmp 	short bufaloc_7        
  2968                              <1> 		; br 1b
  2969                              <1> bufaloc_8: ;1:
  2970 00005E97 891E                <1>         mov	[esi], ebx
  2971                              <1> 		; mov r5,(r2)
  2972                              <1> 	;;pop	esi ; ***
  2973                              <1>        		; mov (sp)+,r2 / restore r2
  2974 00005E99 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  2975                              <1> 		; Retro UNIX 8086 v1 modification
  2976                              <1> 		; zf=1 --> block already is in an I/O buffer
  2977                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  2978 00005E9B C3                  <1> 	retn
  2979                              <1> 		; rts r0
  2980                              <1> 
  2981                              <1> diskio:
  2982                              <1> 	; 12/02/2022
  2983                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  2984                              <1> 	; 10/07/2015
  2985                              <1> 	; 02/07/2015
  2986                              <1> 	; 16/06/2015
  2987                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2988                              <1> 	;	     (80386 protected mode modifications)	
  2989                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2990                              <1> 	;
  2991                              <1> 	; Retro UNIX 8086 v1 feature only !
  2992                              <1> 	;
  2993                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  2994                              <1> 	; 04/07/2009 - 20/07/2011
  2995                              <1> 	;
  2996                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  2997                              <1> 	;
  2998                              <1>         ; INPUTS ->
  2999                              <1> 	; 	   eBX = System I/O Buffer header address
  3000                              <1> 	;
  3001                              <1>         ; OUTPUTS -> cf=0 --> done 
  3002                              <1> 	; 	     cf=1 --> error code in AH
  3003                              <1> 	;
  3004                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3005                              <1> 	
  3006                              <1> ;rw_disk_sector:
  3007                              <1> 	; 12/02/2022
  3008                              <1> 	; 10/07/2015
  3009                              <1> 	; 02/07/2015
  3010                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3011                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3012                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3013                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3014                              <1> 	;
  3015                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3016 00005E9C B602                <1> 	mov	dh, 2
  3017 00005E9E 668B03              <1> 	mov	ax, [ebx] 
  3018                              <1> 	;
  3019 00005EA1 56                  <1> 	push	esi ; ****
  3020 00005EA2 53                  <1> 	push	ebx ; ***
  3021                              <1> 	;
  3022 00005EA3 0FB6C8              <1> 	movzx	ecx, al
  3023 00005EA6 89CE                <1> 	mov	esi, ecx
  3024                              <1> 	;
  3025 00005EA8 38F1                <1> 	cmp	cl, dh ; 2
  3026 00005EAA 7202                <1> 	jb	short rwdsk0
  3027 00005EAC 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3028                              <1> rwdsk0:
  3029 00005EAE A2[3B660000]        <1> 	mov	[drv], al
  3030 00005EB3 81C6[8A660000]      <1> 	add	esi, drv.status
  3031                              <1> 	; 11/06/2015
  3032 00005EB9 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3033 00005EBC 7204                <1> 	jb      short rwdsk1
  3034                              <1> 	; 'drive not ready' error
  3035                              <1> 	; 12/02/2022
  3036                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3037                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3038                              <1> 	;;jmp	error
  3039                              <1> 	;stc	; cf = 1
  3040                              <1> 	;retn
  3041                              <1> 	; 12/02/2022
  3042 00005EBE B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3043 00005EC0 EB20                <1> 	jmp	short rwdsk_err1
  3044                              <1> rwdsk1:
  3045 00005EC2 F6C402              <1> 	test	ah, 2
  3046                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3047                              <1> 			 ; write bit
  3048 00005EC5 7402                <1> 	jz	short rwdsk2
  3049                              <1> 	;test	ah, 4
  3050                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3051                              <1> 	;		 ; read bit
  3052                              <1> 	;jz	short diskio_ret
  3053 00005EC7 FEC6                <1> 	inc	dh ; 03h = write
  3054                              <1> rwdsk2:
  3055 00005EC9 88C2                <1> 	mov	dl, al
  3056 00005ECB 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3057 00005ECE 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3058 00005ED0 C0E102              <1> 	shl	cl, 2
  3059 00005ED3 81C1[6E660000]      <1> 	add	ecx, drv.size ; disk size
  3060 00005ED9 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3061 00005EDB 7214                <1> 	jb      short rwdsk3
  3062                              <1>  	; 'out of volume' error
  3063                              <1> 	; 12/02/2022
  3064                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3065                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3066                              <1> 	;;jmp	error
  3067                              <1> 	;stc	; cf = 1
  3068                              <1> 	;retn
  3069                              <1> 	; 12/02/2022
  3070 00005EDD B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3071                              <1> rwdsk_err1:
  3072 00005EE2 C605[5A6F0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3073 00005EE9 890D[476F0000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3074 00005EEF EB30                <1> 	jmp	short rwdsk_err2
  3075                              <1> rwdsk3:
  3076                              <1> 	; 11/06/2015
  3077 00005EF1 83C304              <1> 	add	ebx, 4 ; buffer address
  3078 00005EF4 C605[766F0000]04    <1> 	mov	byte [retry_count], 4
  3079 00005EFB F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3080 00005EFE 7432                <1>         jz      short rwdsk_chs
  3081                              <1> rwdsk_lba:
  3082                              <1> 	; LBA read/write (with private LBA function) 
  3083                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3084 00005F00 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3085 00005F03 89C1                <1> 	mov	ecx, eax ; sector number
  3086                              <1> 	; ebx = buffer (data) address
  3087                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3088                              <1> rwdsk_lba_retry:
  3089                              <1> 	;mov	dl, [drv]
  3090                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3091 00005F05 B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3092 00005F07 00F4                <1> 	add	ah, dh		
  3093 00005F09 B001                <1> 	mov	al, 1
  3094                              <1> 	;int	13h
  3095 00005F0B E8BEC6FFFF          <1> 	call	int13h
  3096 00005F10 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3097 00005F12 730E                <1> 	jnc	short rwdsk_lba_ok
  3098 00005F14 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3099 00005F17 7408                <1>         je      short rwdsk_lba_fails
  3100 00005F19 FE0D[766F0000]      <1> 	dec	byte [retry_count]
  3101 00005F1F 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3102                              <1> rwdsk_err2:	; 12/02/2022
  3103                              <1> rwdsk_lba_fails:
  3104 00005F21 F9                  <1> 	stc
  3105                              <1> rwdsk_lba_ok:
  3106 00005F22 5B                  <1> 	pop	ebx ; ***
  3107 00005F23 5E                  <1> 	pop	esi ; ****
  3108 00005F24 C3                  <1> 	retn
  3109                              <1> rwdsk_lba_reset:
  3110 00005F25 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3111                              <1> 	;int	13h
  3112 00005F27 E8A2C6FFFF          <1>         call	int13h
  3113 00005F2C 73D7                <1> 	jnc     short rwdsk_lba_retry
  3114 00005F2E 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3115 00005F30 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3116                              <1> 	;
  3117                              <1> 	; CHS read (convert LBA address to CHS values)	
  3118                              <1> rwdsk_chs:
  3119                              <1> 	; 10/07/2015
  3120 00005F32 81EE[8A660000]      <1> 	sub	esi, drv.status
  3121 00005F38 89F1                <1> 	mov	ecx, esi
  3122 00005F3A 81C6[91660000]      <1> 	add 	esi, drv.error
  3123                              <1> 	; 02/07/2015
  3124                              <1> 	; 16/06/2015
  3125                              <1>  	; 11/06/2015 
  3126 00005F40 53                  <1> 	push	ebx ; ** ; buffer
  3127 00005F41 D1E1                <1> 	shl	ecx, 1
  3128 00005F43 51                  <1> 	push	ecx ; * 
  3129                              <1> 	;
  3130 00005F44 89CB                <1> 	mov	ebx, ecx
  3131 00005F46 8835[756F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3132 00005F4C 31D2                <1> 	xor	edx, edx ; 0
  3133                              <1> 	; 04/02/2022
  3134                              <1> 	;sub	ecx, ecx 
  3135 00005F4E 81C3[60660000]      <1>         add     ebx, drv.spt
  3136 00005F54 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3137                              <1> 		; EDX:EAX = LBA
  3138 00005F57 F7F1                <1> 	div	ecx
  3139 00005F59 88D1                <1> 	mov	cl, dl	; sector number - 1
  3140 00005F5B FEC1                <1> 	inc	cl	; sector number (1 based)
  3141 00005F5D 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3142                              <1> 	;push	cx
  3143                              <1>         ; 04/02/2022
  3144 00005F5E 51                  <1> 	push	ecx
  3145 00005F5F 81C3[52660000]      <1>         add     ebx, drv.heads
  3146 00005F65 668B0B              <1> 	mov	cx, [ebx] ; heads
  3147 00005F68 31D2                <1> 	xor	edx, edx
  3148                              <1> 		; EAX = cylinders * heads + head
  3149 00005F6A F7F1                <1> 	div	ecx
  3150                              <1> 	;pop	cx     ; sector number
  3151                              <1> 	; 04/02/2022
  3152 00005F6C 59                  <1> 	pop	ecx
  3153 00005F6D 88D6                <1> 	mov	dh, dl ; head number
  3154 00005F6F 8A15[3B660000]      <1> 	mov	dl, [drv]
  3155 00005F75 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3156 00005F77 C0E406              <1> 	shl	ah, 6
  3157 00005F7A 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3158                              <1> 		       ; sector (bits 0-7)
  3159 00005F7C 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3160                              <1> 		; CL = sector (bits 0-5)
  3161                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3162                              <1> 		; CH = cylinder (bits 0-7)
  3163                              <1> 		; DH = head
  3164                              <1> 		; DL = drive
  3165                              <1> 	;
  3166 00005F7D C605[766F0000]04    <1> 	mov	byte [retry_count], 4
  3167                              <1> rwdsk_retry:	
  3168 00005F84 8A25[756F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3169 00005F8A B001                <1> 	mov	al, 1 ; sector count	
  3170                              <1> 	;int	13h
  3171 00005F8C E83DC6FFFF          <1> 	call	int13h
  3172 00005F91 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3173 00005F93 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3174 00005F95 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3175 00005F98 7408                <1> 	je	short rwdsk_fails
  3176 00005F9A FE0D[766F0000]      <1> 	dec	byte [retry_count]
  3177 00005FA0 7504                <1> 	jnz	short rwdsk_reset
  3178                              <1> rwdsk_fails:
  3179 00005FA2 F9                  <1> 	stc
  3180                              <1> rwdsk_ok:
  3181 00005FA3 5B                  <1> 	pop	ebx ; ***
  3182 00005FA4 5E                  <1> 	pop	esi ; ****
  3183 00005FA5 C3                  <1> 	retn
  3184                              <1> rwdsk_reset:
  3185                              <1> 	; 02/02/2015
  3186 00005FA6 28E4                <1> 	sub	ah, ah
  3187 00005FA8 80FA80              <1> 	cmp	dl, 80h
  3188 00005FAB 7202                <1> 	jb	short rwdsk_fd_reset
  3189 00005FAD B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3190                              <1> rwdsk_fd_reset:
  3191                              <1> 	;int	13h
  3192 00005FAF E81AC6FFFF          <1>         call	int13h
  3193 00005FB4 73CE                <1> 	jnc	short rwdsk_retry
  3194 00005FB6 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3195 00005FB8 EBE9                <1> 	jmp 	short rwdsk_ok
  3196                              <1> 
  3197                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3198                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3199                              <1> ;
  3200                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3201                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3202                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3203                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3204                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3205                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3206                              <1> ; as in original unix v1.
  3207                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3208                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3209                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3210                              <1> ;
  3211                              <1> ; Erdogan tan (10/07/2015) 
  3212                              <1> 
  3213                              <1> ;drum: / interrupt handler
  3214                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3215                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3216                              <1> ;                                      / error
  3217                              <1> ;               br 3f / no, error
  3218                              <1> ;       br      2f / error
  3219                              <1> ;
  3220                              <1> ;disk:
  3221                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3222                              <1> ;       jmp     *$0f
  3223                              <1> ;0:
  3224                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3225                              <1> ;      	        br 3f / no, errors
  3226                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3227                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3228                              <1> ;                        / to 1f
  3229                              <1> ;       br      4f
  3230                              <1> ;1:
  3231                              <1> ;       bit     $20000,rkcs
  3232                              <1> ;       beq     4f / wait for seek complete
  3233                              <1> ;       mov     $0b,0b-2
  3234                              <1> ;       mov     rkap,r1
  3235                              <1> ;2:
  3236                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3237                              <1> ;                          / the disk buffer
  3238                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3239                              <1> ;       inc     r1
  3240                              <1> ;       asr     (r1)
  3241                              <1> ;       asr     (r1)
  3242                              <1> ;       asr     (r1) / reissue request
  3243                              <1> ;       dec     r1
  3244                              <1> ;3:
  3245                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3246                              <1> ;       mov     ac,-(sp)
  3247                              <1> ;       mov     mq,-(sp) / put these on the stack
  3248                              <1> ;       mov     sc,-(sp)
  3249                              <1> ;       jsr     r0,poke
  3250                              <1> ;       mov     (sp)+,sc
  3251                              <1> ;       mov     (sp)+,mq / pop them off stack
  3252                              <1> ;       mov     (sp)+,ac
  3253                              <1> ;4:
  3254                              <1> ;       jmp     retisp / u4-3
  3255                              <1> ;
  3256                              <1> ;trapt:                  / r2 points to the
  3257                              <1> ;       mov     (r0)+,r2 / device control register
  3258                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3259                              <1> ;       tst     (sp)+
  3260                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3261                              <1> ;       bge     4b / device still active so branch
  3262                              <1> ;       bit     (r0),active / was device busy?
  3263                              <1> ;       beq     4b / no, stray interrupt
  3264                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3265                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3266                              <1> ;       bge     2f / if no error jump to 2f
  3267                              <1> ;       tst     (r0)+ / skip on error
  3268                              <1> ; 2:
  3269                              <1> ;       jmp     (r0)
  1997                                  %include 'u9.s'        ; 29/06/2015
  1998                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYS9.INC
  1999                              <1> ; Last Modification: 16/02/2022
  2000                              <1> ; ----------------------------------------------------------------------------
  2001                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2002                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2003                              <1> ;
  2004                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2005                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2006                              <1> ; <Bell Laboratories (17/3/1972)>
  2007                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2008                              <1> ;
  2009                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2010                              <1> ;
  2011                              <1> ; ****************************************************************************
  2012                              <1> ; 21/11/2015
  2013                              <1> 
  2014                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2015                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2016                              <1> 
  2017                              <1> getch:
  2018                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2019                              <1> 	; 30/06/2015
  2020                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2021 00005FBA 28C0                <1> 	sub	al, al ; 0
  2022                              <1> getch_q: ; 06/08/2015
  2023 00005FBC 8A25[766B0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2024 00005FC2 EB06                <1>         jmp     short getc_n
  2025                              <1> 
  2026                              <1> getc: 
  2027                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2028                              <1> 	; 12/11/2015
  2029                              <1> 	; 15/09/2015
  2030                              <1> 	; 01/07/2015
  2031                              <1> 	; 30/06/2015
  2032                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2033                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2034                              <1> 	;
  2035                              <1> 	; Retro UNIX 8086 v1 modification !
  2036                              <1> 	; 
  2037                              <1> 	; 'getc' gets (next) character 
  2038                              <1> 	;	 from requested TTY (keyboard) buffer 
  2039                              <1> 	; INPUTS ->
  2040                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2041                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2042                              <1> 	;	(Keyboard buffer will point to 
  2043                              <1> 	;			next character at next call)
  2044                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2045                              <1> 	;	(Keyboard buffer will point to 
  2046                              <1> 	;			current character at next call)
  2047                              <1> 	; OUTPUTS ->
  2048                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2049                              <1> 	;     			 ZF=0 -> AX has (current) character
  2050                              <1> 	;      AL = ascii code
  2051                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2052                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2053                              <1> 	; Original UNIX V1 'getc': 
  2054                              <1> 	;		get a character off character list
  2055                              <1> 	;
  2056                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2057                              <1> 	;
  2058                              <1> 	; 30/06/2015 (32 bit modifications)
  2059                              <1> 	; 16/07/2013
  2060                              <1> 	; mov 	[getctty], ah
  2061                              <1> 	;
  2062                              <1> 
  2063 00005FC4 8A25[466F0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2064                              <1> getc_n:
  2065                              <1> 	; 30/06/2015
  2066 00005FCA 08E4                <1> 	or	ah, ah
  2067 00005FCC 740D                <1> 	jz	short getc0 
  2068 00005FCE D0E4                <1> 	shl	ah, 1
  2069 00005FD0 0FB6DC              <1> 	movzx	ebx, ah
  2070 00005FD3 81C3[786B0000]      <1> 	add	ebx, ttychr
  2071 00005FD9 EB05                <1> 	jmp	short getc1
  2072                              <1> getc0:
  2073 00005FDB BB[786B0000]        <1> 	mov	ebx, ttychr
  2074                              <1> getc1:
  2075 00005FE0 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2076                              <1> 				; (by kb_int)	
  2077 00005FE3 6609C9              <1> 	or	cx, cx
  2078 00005FE6 7507                <1> 	jnz	short getc2
  2079 00005FE8 20C0                <1> 	and 	al, al
  2080 00005FEA 7415                <1> 	jz	short getc_s
  2081                              <1> 	;xor	ax, ax
  2082                              <1> 	; 24/12/2021
  2083 00005FEC 31C0                <1> 	xor	eax, eax
  2084 00005FEE C3                  <1> 	retn
  2085                              <1> getc2:	
  2086 00005FEF 20C0                <1> 	and	al, al
  2087 00005FF1 6689C8              <1> 	mov	ax, cx
  2088 00005FF4 66B90000            <1> 	mov	cx, 0
  2089 00005FF8 7506                <1> 	jnz	short getc3
  2090                              <1> getc_sn:
  2091 00005FFA 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2092 00005FFD 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2093                              <1> getc3:
  2094 00006000 C3                  <1> 	retn
  2095                              <1> getc_s:
  2096                              <1> 	; 12/11/2015
  2097                              <1> 	; 15/09/2015
  2098                              <1> 	; 01/07/2015
  2099                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2100                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2101                              <1> 	;
  2102                              <1> 	; tty  of the current process is not 
  2103                              <1> 	; current tty (ptty); so, current process only 
  2104                              <1> 	; can use keyboard input when its tty becomes 
  2105                              <1> 	; current tty (ptty).
  2106                              <1> 	; 'sleep' is for preventing an endless lock
  2107                              <1> 	; during this tty input request.
  2108                              <1> 	; (Because, the user is not looking at the video page
  2109                              <1> 	; of the process to undersand there is a keyboard
  2110                              <1> 	; input request.)
  2111                              <1> 	;
  2112                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2113                              <1> 	;
  2114                              <1> 	; 05/10/2013
  2115                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2116                              <1> 	;
  2117                              <1> 	; 10/10/2013
  2118                              <1> gcw0:
  2119 00006001 B10A                <1> 	mov	cl, 10 ; ch = 0
  2120                              <1> gcw1:	
  2121                              <1> 	; 12/11/2015
  2122 00006003 E81DDCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2123                              <1> 	; 10/10/2013
  2124 00006008 E86AEFFFFF          <1> 	call	idle
  2125 0000600D 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2126                              <1> 				; (by kb_int)
  2127 00006010 6609C0              <1> 	or	ax, ax
  2128                              <1> ;	jnz	short gcw3
  2129 00006013 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2130                              <1> 	; 30/06/2015
  2131 00006015 FEC9                <1> 	dec	cl
  2132 00006017 75EA                <1> 	jnz	short gcw1
  2133                              <1> 	;
  2134 00006019 8A25[466F0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2135                              <1> ;	; 10/12/2013
  2136                              <1> ;	cmp 	ah, [ptty]
  2137                              <1> ;	jne	short gcw2
  2138                              <1> ;	; 14/02/2014
  2139                              <1> ;	cmp	byte [u.uno], 1
  2140                              <1> ;	jna	short gcw0		
  2141                              <1> ;gcw2:
  2142 0000601F E8E0EFFFFF          <1> 	call	sleep
  2143                              <1> 	;
  2144                              <1> 	; 20/09/2013
  2145 00006024 8A25[466F0000]      <1> 	mov	ah, [u.ttyn]
  2146 0000602A 30C0                <1> 	xor 	al, al
  2147 0000602C EB9C                <1> 	jmp	short getc_n
  2148                              <1> ;gcw3:
  2149                              <1> gcw2: 	; 15/09/2015
  2150                              <1> 	; 10/10/2013
  2151 0000602E 30C9                <1> 	xor	cl, cl
  2152 00006030 EBC8                <1> 	jmp	short getc_sn
  2153                              <1> 
  2154                              <1> putc:	
  2155                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2156                              <1> 	; 13/08/2015
  2157                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2158                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2159                              <1> 	;
  2160                              <1> 	; Retro UNIX 8086 v1 modification !
  2161                              <1> 	; 
  2162                              <1> 	; 'putc' puts a character 
  2163                              <1> 	;	 onto requested (tty) video page or
  2164                              <1> 	;	 serial port
  2165                              <1> 	; INPUTS ->
  2166                              <1> 	;     AL = ascii code of the character
  2167                              <1> 	;     AH = video page (tty) number (0 to 7)
  2168                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2169                              <1> 	; OUTPUTS ->
  2170                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2171                              <1> 	;      			ZF=0 -> AX has (current) character
  2172                              <1> 	;     cf=0 and AH = 0 -> no error
  2173                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2174                              <1> 	; 
  2175                              <1> 	; Original UNIX V1 'putc': 
  2176                              <1> 	;     put a character at the end of character list
  2177                              <1> 	;
  2178                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2179                              <1> 	;
  2180 00006032 80FC07              <1> 	cmp	ah, 7
  2181                              <1>         ;ja	sndc
  2182 00006035 770A                <1>         ja      short sndc ; 24/12/2024
  2183                              <1> 	; 30/06/2015
  2184 00006037 0FB6DC              <1> 	movzx	ebx, ah
  2185                              <1> 	; 13/08/2015
  2186 0000603A B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2187 0000603C E9B2B3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2188                              <1> 
  2189                              <1> sndc:   ; <Send character>
  2190                              <1> 	;
  2191                              <1> 	; 12/01/2022
  2192                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2193                              <1> 	; 17/11/2015
  2194                              <1> 	; 16/11/2015
  2195                              <1> 	; 11/11/2015
  2196                              <1> 	; 10/11/2015
  2197                              <1> 	; 09/11/2015
  2198                              <1> 	; 08/11/2015
  2199                              <1> 	; 07/11/2015
  2200                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2201                              <1> 	; 29/10/2015
  2202                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2203                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2204                              <1> 	;
  2205                              <1> 	; Retro UNIX 8086 v1 feature only !
  2206                              <1> 	;
  2207                              <1> 	; ah = [u.ttyn]
  2208                              <1> 	;
  2209                              <1> 	; 30/06/2015
  2210 00006041 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2211                              <1> 	; 07/11/2015
  2212 00006044 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2213                              <1> sndc0:
  2214                              <1> 	; 07/11/2015
  2215 00006047 E806F0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2216 0000604C 7405                <1> 	jz	short sndc1
  2217 0000604E E8D2DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2218                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2219                              <1> sndc1:
  2220                              <1> 	; 16/11/2015
  2221                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2222                              <1> 	; 24/12/2021
  2223 00006053 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2224                              <1> sndcx:
  2225 00006055 8A83[BA6B0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2226 0000605B 8AA3[B86B0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2227                              <1> 	;
  2228                              <1> 	; 17/11/2015
  2229                              <1> 	; check 'request for response' status
  2230 00006061 80BB[B46B0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2231 00006068 740A                <1> 	jz	short query
  2232                              <1> response:
  2233 0000606A FE05[B76B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2234 00006070 B0FF                <1> 	mov	al, 0FFh	 
  2235 00006072 EB14                <1> 	jmp	short sndc3
  2236                              <1> query:
  2237 00006074 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2238 00006076 750E                <1> 	jnz 	short sndc2 ; normal character
  2239                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2240                              <1> 	;je	short sndc2  ; yes, already responded
  2241                              <1> 	; 16/11/2015
  2242                              <1> 	; query: request for response (again)
  2243 00006078 8883[B86B0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2244 0000607E FE05[B76B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2245 00006084 EB02                <1> 	jmp	short sndc3
  2246                              <1> sndc2:
  2247 00006086 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2248                              <1> sndc3:
  2249 00006088 8883[BA6B0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2250 0000608E 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2251                              <1> 	; 30/06/2015
  2252 00006090 E830D5FFFF          <1> 	call	sp_status ; get serial port status
  2253                              <1> 	; AL = Line status, AH = Modem status
  2254                              <1> 	; 07/11/2015
  2255 00006095 A880                <1> 	test	al, 80h
  2256 00006097 7504                <1> 	jnz	short sndc4
  2257 00006099 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2258 0000609B 751A                <1> 	jnz	short sndc5
  2259                              <1> sndc4: 	; Check line status again
  2260                              <1> 	; 16/11/2015
  2261                              <1> 	;push	cx
  2262                              <1> 	; 24/12/2021
  2263 0000609D 51                  <1> 	push	ecx
  2264                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2265                              <1> 	; 12/01/2022
  2266 0000609E 31C9                <1> 	xor	ecx, ecx
  2267 000060A0 B106                <1> 	mov	cl, 6
  2268 000060A2 E843B4FFFF          <1> 	call	WAITF
  2269                              <1> 	;pop	cx
  2270                              <1> 	; 24/12/1021
  2271 000060A7 59                  <1> 	pop	ecx
  2272                              <1> 	;
  2273 000060A8 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2274 000060AA E816D5FFFF          <1> 	call	sp_status ; get serial port status
  2275                              <1> 	; 16/11/2015
  2276                              <1> 	; 09/11/2015
  2277                              <1> 	; 08/11/2015
  2278 000060AF A880                <1> 	test	al, 80h	; time out error
  2279 000060B1 7565                <1>         jnz     short sndc7
  2280 000060B3 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2281 000060B5 7461                <1>         jz	short sndc7
  2282                              <1> sndc5:  
  2283 000060B7 8A83[BA6B0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2284 000060BD 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2285 000060C1 28DE                <1> 	sub	dh, bl
  2286 000060C3 EE                  <1> 	out	dx, al	   ; send on serial port
  2287                              <1> 	; 10/11/2015
  2288                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2289                              <1> 	; (to improve text flow to the terminal)
  2290                              <1> 	; ('diskette.inc': 'WAITF')
  2291                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2292                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2293                              <1> 	;push	cx
  2294                              <1> 	; 24/12/2021
  2295 000060C4 51                  <1> 	push	ecx
  2296                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2297                              <1> 	; 12/01/2022
  2298 000060C5 29C9                <1> 	sub	ecx, ecx
  2299 000060C7 B106                <1> 	mov	cl, 6
  2300 000060C9 E81CB4FFFF          <1> 	call	WAITF
  2301                              <1> 	;pop	cx
  2302                              <1> 	; 24/12/1021
  2303 000060CE 59                  <1> 	pop	ecx
  2304                              <1>     	;
  2305                              <1> 	; 07/11/2015
  2306 000060CF 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2307                              <1> 	;
  2308 000060D1 E8EFD4FFFF          <1> 	call	sp_status ; get serial port status
  2309                              <1> 	; AL = Line status, AH = Modem status
  2310                              <1> 	;
  2311 000060D6 E877EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2312 000060DB 7405                <1> 	jz	short sndc6
  2313 000060DD E843DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2314                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2315                              <1> sndc6:
  2316 000060E2 3C80                <1> 	cmp	al, 80h
  2317 000060E4 7332                <1> 	jnb	short sndc7		
  2318                              <1> 	;
  2319 000060E6 803D[B76B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2320 000060ED 7244                <1> 	jb	short sndc8 	; no, normal character
  2321 000060EF 883D[B76B0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2322                              <1> 	; 17/11/2015
  2323 000060F5 E87DEEFFFF          <1> 	call	idle
  2324                              <1> 	;
  2325 000060FA 38BB[BA6B0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2326                              <1>         ;ja	sndc2       ; response (will be followed by
  2327                              <1> 			    ; a normal character)
  2328                              <1> 	; 24/12/2021
  2329 00006100 7602                <1> 	jna	short sndc_10
  2330 00006102 EB82                <1> 	jmp	sndc2
  2331                              <1> sndc_10:
  2332                              <1> 	; Query request must be responded by the terminal
  2333                              <1> 	; before sending a normal character !
  2334 00006104 53                  <1> 	push	ebx
  2335                              <1> 	;push	cx ; *** cl = character (to be sent)
  2336                              <1> 	; 24/12/2021
  2337 00006105 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2338 00006106 8A25[466F0000]      <1> 	mov	ah, [u.ttyn]
  2339 0000610C E8F3EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2340                              <1> 		      ; received data available interrupt
  2341                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2342                              <1> 	; 24/12/2021
  2343 00006111 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2344 00006112 5B                  <1> 	pop	ebx
  2345 00006113 E93DFFFFFF          <1>         jmp	sndcx
  2346                              <1> sndc7:
  2347                              <1> 	 ; 16/11/2015
  2348 00006118 803D[B76B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2349 0000611F 7213                <1> 	jb	short sndc9 	; no
  2350                              <1> 	;
  2351 00006121 88BB[B86B0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2352 00006127 88BB[BA6B0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2353                              <1> 	;
  2354 0000612D 883D[B76B0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2355                              <1> sndc8:
  2356 00006133 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2357                              <1> sndc9:
  2358                              <1> 	; AL = Line status, AH = Modem status
  2359 00006134 C3                  <1> 	retn
  2360                              <1> 
  2361                              <1> get_cpos:
  2362                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2363                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2364                              <1> 	;
  2365                              <1> 	; INPUT -> bl = video page number
  2366                              <1> 	; RETURN -> dx = cursor position
  2367                              <1> 
  2368 00006135 53                  <1> 	push	ebx
  2369 00006136 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2370 00006139 D0E3                <1> 	shl	bl, 1
  2371 0000613B 81C3[666B0000]      <1> 	add	ebx, cursor_posn
  2372 00006141 668B13              <1> 	mov	dx, [ebx]
  2373 00006144 5B                  <1> 	pop	ebx
  2374 00006145 C3                  <1> 	retn
  2375                              <1> 
  2376                              <1> read_ac_current:
  2377                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2378                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2379                              <1> 	;
  2380                              <1> 	; INPUT -> bl = video page number
  2381                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2382                              <1> 
  2383 00006146 E812B4FFFF          <1> 	call 	find_position ; 'video.inc'
  2384                              <1> 	; dx = status port
  2385                              <1> 	; esi = cursor location/address
  2386 0000614B 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2387 00006151 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2388 00006154 C3                  <1> 	retn
  2389                              <1> 
  2390                              <1> syssleep:
  2391                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2392                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2393                              <1> 	;
  2394                              <1> 	; Retro UNIX 8086 v1 feature only
  2395                              <1> 	; (INPUT -> none)
  2396                              <1> 	;
  2397 00006155 0FB61D[416F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2398 0000615C 8AA3[556C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2399 00006162 E89DEEFFFF          <1> 	call	sleep
  2400 00006167 E9D7D9FFFF          <1> 	jmp	sysret
  2401                              <1> 
  2402                              <1> vp_clr:
  2403                              <1> 	; Reset/Clear Video Page
  2404                              <1> 	;
  2405                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2406                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2407                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2408                              <1> 	;
  2409                              <1> 	; Retro UNIX 8086 v1 feature only !
  2410                              <1> 	;
  2411                              <1> 	; INPUTS -> 
  2412                              <1> 	;   BL = video page number	 
  2413                              <1> 	;
  2414                              <1> 	; OUTPUT ->
  2415                              <1> 	;   none
  2416                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2417                              <1> 	;
  2418                              <1> 	; 04/12/2013
  2419 0000616C 28C0                <1> 	sub	al, al
  2420                              <1> 	; al = 0 (clear video page)
  2421                              <1> 	; bl = video page
  2422 0000616E B407                <1> 	mov	ah, 07h
  2423                              <1> 	; ah = 7 (attribute/color)
  2424                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2425                              <1> 	; 24/12/2021
  2426 00006170 31C9                <1> 	xor	ecx, ecx
  2427 00006172 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2428 00006176 E80CB4FFFF          <1> 	call	scroll_up
  2429                              <1> 	; bl = video page
  2430                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2431                              <1> 	; 24/12/2021
  2432 0000617B 31D2                <1> 	xor	edx, edx 
  2433 0000617D E97BB3FFFF          <1> 	jmp 	set_cpos
  2434                              <1> 
  2435                              <1> sysmsg:
  2436                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2437                              <1> 	; 11/11/2015
  2438                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2439                              <1> 	; Print user-application message on user's console tty
  2440                              <1> 	;
  2441                              <1> 	; Input -> EBX = Message address
  2442                              <1> 	;	   ECX = Message length (max. 255)
  2443                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2444                              <1> 	;
  2445 00006182 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2446                              <1> 	;ja	sysret ; nothing to do with big message size
  2447 00006188 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2448 0000618A 08C9                <1> 	or	cl, cl
  2449                              <1> 	;jz	sysret
  2450 0000618C 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2451 0000618E 20D2                <1> 	and	dl, dl
  2452 00006190 7502                <1> 	jnz	short sysmsg0
  2453 00006192 B207                <1> 	mov	dl, 07h ; default color
  2454                              <1> 		; (black background, light gray character)
  2455                              <1> sysmsg0:
  2456 00006194 891D[186F0000]      <1> 	mov	[u.base], ebx
  2457 0000619A 8815[776B0000]      <1> 	mov	[ccolor], dl ; color attributes
  2458 000061A0 89E5                <1> 	mov	ebp, esp
  2459 000061A2 31DB                <1> 	xor	ebx, ebx ; 0
  2460 000061A4 891D[206F0000]      <1> 	mov	[u.nread], ebx ; 0
  2461                              <1> 	;
  2462 000061AA 381D[596F0000]      <1> 	cmp	[u.kcall], bl ; 0
  2463 000061B0 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2464                              <1> 	;
  2465 000061B2 890D[1C6F0000]      <1> 	mov	[u.count], ecx
  2466 000061B8 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2467                              <1> 	; 24/12/2021
  2468                              <1> 	; (dword alignment for esp)
  2469 000061B9 F6C103              <1> 	test	cl, 3
  2470 000061BC 7404                <1> 	jz	short sysmsg_7
  2471 000061BE 80C903              <1> 	or	cl, 3
  2472 000061C1 41                  <1> 	inc	ecx
  2473                              <1> sysmsg_7:
  2474 000061C2 29CC                <1> 	sub	esp, ecx
  2475 000061C4 89E7                <1> 	mov	edi, esp
  2476 000061C6 89E6                <1> 	mov	esi, esp
  2477 000061C8 66891D[576F0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2478                              <1> 	; 11/11/2015
  2479 000061CF 8A25[286F0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2480                              <1> 	; 0 = none
  2481 000061D5 FECC                <1> 	dec	ah
  2482 000061D7 790C                <1> 	jns	short sysmsg1 
  2483 000061D9 8A1D[416F0000]      <1> 	mov	bl, [u.uno] ; process number	
  2484 000061DF 8AA3[556C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2485                              <1> sysmsg1:
  2486 000061E5 8825[466F0000]      <1> 	mov	[u.ttyn], ah
  2487                              <1> sysmsg2:
  2488 000061EB E86AF5FFFF          <1> 	call	cpass
  2489 000061F0 7416                <1> 	jz	short sysmsg5
  2490 000061F2 AA                  <1> 	stosb
  2491 000061F3 20C0                <1> 	and	al, al
  2492 000061F5 75F4                <1> 	jnz	short sysmsg2
  2493                              <1> sysmsg3:
  2494 000061F7 80FC07              <1> 	cmp	ah, 7 ; tty number
  2495 000061FA 7711                <1> 	ja	short sysmsg6 ; serial port
  2496 000061FC E83E000000          <1> 	call	print_cmsg
  2497                              <1> sysmsg4:
  2498 00006201 89EC                <1> 	mov	esp, ebp	
  2499                              <1> sysmsg8: ; 24/12/2021	
  2500 00006203 E93BD9FFFF          <1> 	jmp	sysret
  2501                              <1> sysmsg5:
  2502 00006208 C60700              <1> 	mov	byte [edi], 0
  2503 0000620B EBEA                <1> 	jmp	short sysmsg3
  2504                              <1> sysmsg6:
  2505 0000620D 8A06                <1> 	mov	al, [esi]
  2506 0000620F E82DFEFFFF          <1> 	call	sndc
  2507 00006214 72EB                <1> 	jc	short sysmsg4
  2508 00006216 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2509 00006219 76E6                <1> 	jna	short sysmsg4
  2510 0000621B 46                  <1> 	inc 	esi
  2511 0000621C 8A25[466F0000]      <1> 	mov	ah, [u.ttyn]
  2512 00006222 EBE9                <1> 	jmp	short sysmsg6
  2513                              <1> 
  2514                              <1> sysmsgk: ; Temporary (01/07/2015)
  2515                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2516                              <1> 	; (ECX -character count- will not be considered)
  2517 00006224 8B35[186F0000]      <1> 	mov	esi, [u.base]
  2518 0000622A 8A25[766B0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2519 00006230 8825[466F0000]      <1> 	mov	[u.ttyn], ah
  2520 00006236 C605[596F0000]00    <1> 	mov	byte [u.kcall], 0
  2521 0000623D EBB8                <1> 	jmp	short sysmsg3
  2522                              <1> 	
  2523                              <1> print_cmsg: 
  2524                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2525                              <1> 	;
  2526                              <1> 	; print message (on user's console tty) 
  2527                              <1> 	;	with requested color
  2528                              <1> 	;
  2529                              <1> 	; INPUTS:
  2530                              <1> 	;	esi = message address
  2531                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2532                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2533                              <1> 	;
  2534 0000623F AC                  <1> 	lodsb
  2535                              <1> pcmsg1:
  2536 00006240 56                  <1> 	push 	esi
  2537 00006241 0FB61D[466F0000]    <1>         movzx   ebx, byte [u.ttyn]
  2538 00006248 8A25[776B0000]      <1> 	mov	ah, [ccolor]
  2539 0000624E E8A0B1FFFF          <1> 	call 	write_tty
  2540 00006253 5E                  <1> 	pop	esi
  2541 00006254 AC                  <1> 	lodsb
  2542 00006255 20C0                <1> 	and 	al, al  ; 0
  2543 00006257 75E7                <1> 	jnz 	short pcmsg1
  2544 00006259 C3                  <1> 	retn
  2545                              <1> 
  2546                              <1> sysgeterr:
  2547                              <1> 	; 16/02/2022
  2548                              <1> 	; 09/12/2015
  2549                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2550                              <1> 	; Get last error number or page fault count
  2551                              <1> 	; (for debugging)
  2552                              <1> 	;
  2553                              <1> 	; Input -> EBX = return type
  2554                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2555                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2556                              <1> 	;	   FFFFFFFEh = total page fault count
  2557                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2558                              <1> 	;
  2559                              <1> 	; Output -> EAX = last error number or page fault count
  2560                              <1> 	;	   (depending on EBX input)
  2561                              <1> 	; 	
  2562 0000625A 21DB                <1> 	and 	ebx, ebx
  2563 0000625C 750F                <1> 	jnz	short glerr_2
  2564                              <1> glerr_0:
  2565 0000625E A1[476F0000]        <1> 	mov	eax, [u.error]
  2566                              <1> glerr_1:
  2567 00006263 A3[F86E0000]        <1> 	mov	[u.r0], eax
  2568                              <1>  	;retn
  2569                              <1> 	; 16/02/2022 (BugFix)
  2570 00006268 E9D6D8FFFF          <1> 	jmp	sysret
  2571                              <1> glerr_2:
  2572 0000626D 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2573 0000626E 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2574 00006270 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2575 00006271 75EB                <1> 	jnz	short glerr_0
  2576 00006273 A1[C07F0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2577 00006278 EBE9                <1>         jmp     short glerr_1
  2578                              <1> glerr_3:
  2579 0000627A A1[5B6F0000]        <1> 	mov 	eax, [u.pfcount]
  2580 0000627F EBE2                <1> 	jmp	short glerr_1
  1998                                  
  1999                                  ; 07/03/2015
  2000                                  ; Temporary Code
  2001                                  display_disks:
  2002 00006281 803D[3E660000]00        	cmp 	byte [fd0_type], 0
  2003 00006288 7605                    	jna 	short ddsks1
  2004 0000628A E87D000000              	call	pdskm
  2005                                  ddsks1:
  2006 0000628F 803D[3F660000]00        	cmp	byte [fd1_type], 0
  2007 00006296 760C                    	jna	short ddsks2
  2008 00006298 C605[2D680000]31        	mov	byte [dskx], '1'
  2009 0000629F E868000000              	call	pdskm
  2010                                  ddsks2:
  2011 000062A4 803D[40660000]00        	cmp	byte [hd0_type], 0
  2012 000062AB 7654                    	jna	short ddsk6
  2013 000062AD 66C705[2B680000]68-     	mov	word [dsktype], 'hd'
  2013 000062B5 64                 
  2014 000062B6 C605[2D680000]30        	mov	byte [dskx], '0'
  2015 000062BD E84A000000              	call	pdskm
  2016                                  ddsks3:
  2017 000062C2 803D[41660000]00        	cmp	byte [hd1_type], 0
  2018 000062C9 7636                    	jna	short ddsk6
  2019 000062CB C605[2D680000]31        	mov	byte [dskx], '1'
  2020 000062D2 E835000000              	call	pdskm
  2021                                  ddsks4:
  2022 000062D7 803D[42660000]00        	cmp	byte [hd2_type], 0
  2023 000062DE 7621                    	jna	short ddsk6
  2024 000062E0 C605[2D680000]32        	mov	byte [dskx], '2'
  2025 000062E7 E820000000              	call	pdskm
  2026                                  ddsks5:
  2027 000062EC 803D[43660000]00        	cmp	byte [hd3_type], 0
  2028 000062F3 760C                    	jna	short ddsk6
  2029 000062F5 C605[2D680000]33        	mov	byte [dskx], '3'
  2030 000062FC E80B000000              	call	pdskm
  2031                                  ddsk6:
  2032 00006301 BE[3C680000]            	mov	esi, nextline
  2033 00006306 E806000000              	call	pdskml
  2034                                  pdskm_ok:
  2035 0000630B C3                      	retn
  2036                                  pdskm:
  2037 0000630C BE[29680000]            	mov	esi, dsk_ready_msg
  2038                                  pdskml:	
  2039 00006311 AC                      	lodsb
  2040 00006312 08C0                    	or	al, al
  2041 00006314 74F5                    	jz	short pdskm_ok
  2042 00006316 56                      	push	esi
  2043 00006317 31DB                    	xor	ebx, ebx ; 0
  2044                                  			; Video page 0 (bl=0)
  2045 00006319 B407                    	mov	ah, 07h ; Black background, 
  2046                                  			; light gray forecolor
  2047 0000631B E8D3B0FFFF              	call	write_tty
  2048 00006320 5E                      	pop	esi
  2049 00006321 EBEE                    	jmp	short pdskml
  2050                                  
  2051 00006323 90<rep Dh>              align 16
  2052                                  
  2053                                  gdt:	; Global Descriptor Table
  2054                                  	; (30/07/2015, conforming cs)
  2055                                  	; (26/03/2015)
  2056                                  	; (24/03/2015, tss)
  2057                                  	; (19/03/2015)
  2058                                  	; (29/12/2013)
  2059                                  	;
  2060 00006330 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2061                                  	; 18/08/2014
  2062                                  			; 8h kernel code segment, base = 00000000h		
  2063 00006338 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2064                                  			; 10h kernel data segment, base = 00000000h	
  2065 00006340 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2066                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2067 00006348 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2068                                  			; 23h user data segment, base address = 400000h ; CORE
  2069 00006350 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2070                                  			; Task State Segment
  2071 00006358 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2072                                  			       ;  no IO permission in ring 3)
  2073                                  gdt_tss0:
  2074 0000635A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2075                                  gdt_tss1:
  2076 0000635C 00                      	db 0  ; TSS base address, bits 16-23 
  2077                                  	      		; 49h	
  2078 0000635D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2079 0000635E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2080                                  gdt_tss2:
  2081 0000635F 00                      	db 0  ; TSS base address, bits 24-31 
  2082                                  
  2083                                  gdt_end:
  2084                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2085                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2086                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2087                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2088                                  
  2089                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2090                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2091                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2092                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2093                                  		; W= Writeable, A= Accessed
  2094                                  	
  2095                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2096                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2097                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2098                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2099                                  
  2100                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2101                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2102                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2103                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2104                                  	
  2105                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2106                                  
  2107                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2108                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2109                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2110                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2111                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2112                                  		; AVL= Available to programmers	
  2113                                  
  2114                                  gdtd:
  2115 00006360 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2116 00006362 [30630000]                      dd gdt			; Address of the GDT
  2117                                  
  2118                                  	; 20/08/2014
  2119                                  idtd:
  2120 00006366 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2121 00006368 [E0680000]                      dd idt			; Address of the IDT
  2122                                  
  2123                                  Align 4
  2124                                  
  2125                                  	; 21/08/2014
  2126                                  ilist:
  2127                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2128                                  	;
  2129                                  	; Exception list
  2130                                  	; 25/08/2014	
  2131 0000636C [4A080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2132 00006370 [51080000]              	dd	exc1	
  2133 00006374 [58080000]              	dd 	exc2	
  2134 00006378 [5F080000]              	dd	exc3	
  2135 0000637C [63080000]              	dd	exc4	
  2136 00006380 [67080000]              	dd	exc5	
  2137 00006384 [6B080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2138 00006388 [6F080000]              	dd	exc7	
  2139 0000638C [73080000]              	dd	exc8	
  2140 00006390 [77080000]              	dd	exc9	
  2141 00006394 [7B080000]              	dd 	exc10	
  2142 00006398 [7F080000]              	dd	exc11
  2143 0000639C [83080000]              	dd	exc12
  2144 000063A0 [87080000]              	dd	exc13	; 0Dh, General Protection Fault
  2145 000063A4 [8B080000]              	dd 	exc14	; 0Eh, Page Fault
  2146 000063A8 [8F080000]              	dd	exc15
  2147 000063AC [93080000]              	dd	exc16
  2148 000063B0 [97080000]              	dd	exc17
  2149 000063B4 [9B080000]              	dd 	exc18
  2150 000063B8 [9F080000]              	dd	exc19
  2151 000063BC [A3080000]              	dd 	exc20
  2152 000063C0 [A7080000]              	dd	exc21
  2153 000063C4 [AB080000]              	dd	exc22
  2154 000063C8 [AF080000]              	dd	exc23
  2155 000063CC [B3080000]              	dd 	exc24
  2156 000063D0 [B7080000]              	dd	exc25
  2157 000063D4 [BB080000]              	dd	exc26
  2158 000063D8 [BF080000]              	dd	exc27
  2159 000063DC [C3080000]              	dd 	exc28
  2160 000063E0 [C7080000]              	dd	exc29
  2161 000063E4 [CB080000]              	dd 	exc30
  2162 000063E8 [CF080000]              	dd	exc31
  2163                                  	; Interrupt list
  2164 000063EC [7C060000]              	dd	timer_int	; INT 20h
  2165                                  		;dd	irq0	
  2166 000063F0 [910B0000]              	dd	keyb_int	; 27/08/2014
  2167                                  		;dd	irq1
  2168 000063F4 [A0070000]              	dd	irq2
  2169                                  		; COM2 int
  2170 000063F8 [A4070000]              	dd	irq3
  2171                                  		; COM1 int
  2172 000063FC [AF070000]              	dd	irq4
  2173 00006400 [BA070000]              	dd	irq5
  2174                                  ;DISKETTE_INT: ;06/02/2015
  2175 00006404 [7B250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2176                                  		;dd	irq6
  2177                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2178                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2179 00006408 [3E0B0000]              	dd	default_irq7	; 25/02/2015
  2180                                  		;dd	irq7
  2181                                  ; Real Time Clock Interrupt
  2182 0000640C [D9090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2183                                  		;dd	irq8	; INT 28h
  2184 00006410 [CA070000]              	dd	irq9
  2185 00006414 [CE070000]              	dd	irq10
  2186 00006418 [D2070000]              	dd	irq11
  2187 0000641C [D6070000]              	dd	irq12
  2188 00006420 [DA070000]              	dd	irq13
  2189                                  ;HDISK_INT1:  ;06/02/2015 	
  2190 00006424 [A12D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2191                                  		;dd	irq14
  2192                                  ;HDISK_INT2:  ;06/02/2015
  2193 00006428 [C42D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2194                                  		;dd	irq15	; INT 2Fh
  2195                                  		; 14/08/2015
  2196 0000642C [253A0000]              	dd	sysent		; INT 30h (system calls)
  2197                                  	
  2198                                  	;dd	ignore_int
  2199 00006430 00000000                	dd	0
  2200                                  
  2201                                  ;;;
  2202                                  ;;; 11/03/2015
  2203                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2204                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2205                              <1> ; Last Modification: 11/03/2015
  2206                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2207                              <1> ;
  2208                              <1> ; ///////// KEYBOARD DATA ///////////////
  2209                              <1> 
  2210                              <1> ; 05/12/2014
  2211                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2212                              <1> ; 03/06/86  KEYBOARD BIOS
  2213                              <1> 
  2214                              <1> ;---------------------------------------------------------------------------------
  2215                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2216                              <1> ;---------------------------------------------------------------------------------
  2217                              <1> 
  2218                              <1> ;-----	TABLES FOR ALT CASE ------------
  2219                              <1> ;-----	ALT-INPUT-TABLE 
  2220 00006434 524F50514B          <1> K30:	db	82,79,80,81,75
  2221 00006439 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2222                              <1> ;-----	SUPER-SHIFT-TABLE 
  2223 0000643E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2224 00006444 161718191E1F        <1> 	db	22,23,24,25,30,31
  2225 0000644A 202122232425        <1> 	db	32,33,34,35,36,37
  2226 00006450 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2227 00006456 3132                <1> 	db	49,50
  2228                              <1> 
  2229                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2230                              <1> ;-----	KEY_TABLE 
  2231 00006458 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2232 00006459 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2233 0000645E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2234                              <1> _K6L    equ     $-_K6
  2235                              <1> 
  2236                              <1> ;-----	MASK_TABLE
  2237 00006460 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2238 00006461 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2239 00006466 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2240                              <1> 
  2241                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2242 00006468 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2243 0000646E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2244 00006474 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2245 0000647A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2246 00006480 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2247 00006486 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2248 0000648C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2249 00006492 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2250 00006498 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2251 0000649E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2252                              <1> 	;				;----- FUNCTIONS ------		
  2253 000064A2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2254 000064A8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2255 000064AE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2256 000064B4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2257 000064BA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2258                              <1> 
  2259                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2260 000064C0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2260 000064C9 39302D3D0809        <1>
  2261 000064CF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2261 000064D8 705B5D0DFF61736466- <1>
  2261 000064E1 67686A6B6C3B27      <1>
  2262 000064E8 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2262 000064F1 6D2C2E2FFF2AFF20FF  <1>
  2263                              <1> ;-----	LC TABLE SCAN
  2264 000064FA 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2265 000064FF 4041424344          <1> 	db	64,65,66,67,68
  2266 00006504 FFFF                <1> 	db	-1,-1			; NL, SL
  2267                              <1> 
  2268                              <1> ;-----	KEYPAD TABLE
  2269 00006506 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2270 0000650C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2271 00006513 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2272                              <1> 
  2273                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2274 00006518 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2274 00006521 28295F2B0800        <1>
  2275 00006527 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2275 00006530 507B7D0DFF41534446- <1>
  2275 00006539 47484A4B4C3A22      <1>
  2276 00006540 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2276 00006549 4D3C3E3FFF2AFF20FF  <1>
  2277                              <1> ;-----	UC TABLE SCAN
  2278 00006552 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2279 00006557 595A5B5C5D          <1> 	db	89,90,91,92,93
  2280 0000655C FFFF                <1> 	db	-1,-1			; NL, SL
  2281                              <1> 
  2282                              <1> ;-----	NUM STATE TABLE
  2283 0000655E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2283 00006567 3233302E            <1>
  2284                              <1> 	;
  2285 0000656B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2286                              <1> 
  2287                              <1> Align	4
  2288                              <1> ;----------------------------------------
  2289                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2290                              <1> ;----------------------------------------
  2291 00006570 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2292 00006571 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2293                              <1> 				; (29h default setting for video mode 3)
  2294                              <1> 				; Mode Select register Bits
  2295                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2296                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2297                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2298                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2299                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2300                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2301                              <1> 				;   BIT 6, 7 - Not Used
  2302                              <1> 
  2303                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2304                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2305                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2306                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2307                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2308                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2309                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2310                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2311                              <1> ; Mode & 37h = Video signal OFF
  2312                              <1> 			
  2313                              <1> 
  2314                              <1> ; 26/08/2014
  2315                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2316                              <1> ; Derived from IBM "pc-at" 
  2317                              <1> ; rombios source code (06/10/1985)
  2318                              <1> ; 'dseg.inc'
  2319                              <1> 
  2320                              <1> ;---------------------------------------;
  2321                              <1> ;	SYSTEM DATA AREA		;
  2322                              <1> ;----------------------------------------
  2323 00006572 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2324                              <1> 
  2325                              <1> ;----------------------------------------
  2326                              <1> ;	KEYBOARD DATA AREAS		;
  2327                              <1> ;----------------------------------------
  2328                              <1> 
  2329 00006573 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2330 00006574 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2331 00006575 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2332 00006576 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2333 00006577 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2334 00006578 [88650000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2335 0000657C [A8650000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2336 00006580 [88650000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2337 00006584 [88650000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2338                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2339 00006588 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2340                              <1> 
  2341                              <1> ; /// End Of KEYBOARD DATA ///
  2204                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2205                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2206                              <1> ; Last Modification: 11/03/2015
  2207                              <1> ;		    (Data section for 'VIDEO.INC')	
  2208                              <1> ;
  2209                              <1> ; ///////// VIDEO DATA ///////////////
  2210                              <1> 
  2211                              <1> video_params:
  2212                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2213                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2214                              <1> 	; VIDEO MODE 3
  2215 000065A8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2216 000065AF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2217 000065B4 00000000            <1> 	db	0,0,0,0
  2218                              <1> 
  2219                              <1> ; /// End Of VIDEO DATA ///
  2205                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2206                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2207                              <1> ; Last Modification: 11/03/2015
  2208                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2209                              <1> ;
  2210                              <1> ; *****************************************************************************
  2211                              <1> 
  2212                              <1> ;----------------------------------------
  2213                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2214                              <1> ;	REFERENCED BY POST & BIOS	:
  2215                              <1> ;----------------------------------------
  2216                              <1> 
  2217 000065B8 [1B660000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2218                              <1> 
  2219                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2220                              <1> ;----------------------------------------------------------------
  2221                              <1> ; DISK_BASE							:
  2222                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2223                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2224                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2225                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2226                              <1> ;----------------------------------------------------------------
  2227                              <1> 
  2228                              <1> ;DISK_BASE:	
  2229                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2230                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2231                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2232                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2233                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2234                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2235                              <1> ;	DB	01BH		; GAP LENGTH
  2236                              <1> ;	DB	0FFH		; DTL
  2237                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2238                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2239                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2240                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2241                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2242                              <1> 
  2243                              <1> ;----------------------------------------
  2244                              <1> ;	ROM BIOS DATA AREAS		:
  2245                              <1> ;----------------------------------------
  2246                              <1> 
  2247                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2248                              <1> 
  2249                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2250                              <1> 
  2251                              <1> ;----------------------------------------
  2252                              <1> ;	DISKETTE DATA AREAS		:
  2253                              <1> ;----------------------------------------
  2254                              <1> 
  2255                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2256                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2257                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2258                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2259                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2260                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2261                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2262                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2263                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2264                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2265                              <1> 
  2266                              <1> ;----------------------------------------
  2267                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2268                              <1> ;----------------------------------------
  2269                              <1> 
  2270                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2271                              <1> 
  2272                              <1> ;----------------------------------------
  2273                              <1> ;	TIMER DATA AREA 		:
  2274                              <1> ;----------------------------------------
  2275                              <1> 
  2276                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2277                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2278                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2279                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2280                              <1> 
  2281                              <1> ;----------------------------------------
  2282                              <1> ;	ADDITIONAL MEDIA DATA		:
  2283                              <1> ;----------------------------------------
  2284                              <1> 
  2285                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2286                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2287                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2288                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2289                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2290                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2291                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2292                              <1> 
  2293                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2294                              <1> 
  2295                              <1> ;--------------------------------------------------------
  2296                              <1> ;	DRIVE TYPE TABLE				:
  2297                              <1> ;--------------------------------------------------------
  2298                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2299                              <1> DR_TYPE:
  2300 000065BC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2301                              <1>                 ;DW      MD_TBL1
  2302 000065BD [DA650000]          <1> 		dd	MD_TBL1
  2303 000065C1 82                  <1> 		DB	02+BIT7ON
  2304                              <1> 		;DW      MD_TBL2
  2305 000065C2 [E7650000]          <1>                 dd      MD_TBL2
  2306 000065C6 02                  <1> DR_DEFAULT:	DB	02
  2307                              <1>                 ;DW      MD_TBL3
  2308 000065C7 [F4650000]          <1> 		dd      MD_TBL3
  2309 000065CB 03                  <1> 		DB	03
  2310                              <1>                 ;DW      MD_TBL4
  2311 000065CC [01660000]          <1> 		dd      MD_TBL4
  2312 000065D0 84                  <1> 		DB	04+BIT7ON
  2313                              <1>                 ;DW      MD_TBL5
  2314 000065D1 [0E660000]          <1> 		dd      MD_TBL5
  2315 000065D5 04                  <1> 		DB	04
  2316                              <1>                 ;DW      MD_TBL6
  2317 000065D6 [1B660000]          <1> 		dd      MD_TBL6
  2318                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2319                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2320                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2321                              <1> ;--------------------------------------------------------
  2322                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2323                              <1> ;--------------------------------------------------------
  2324                              <1> ;--------------------------------------------------------
  2325                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2326                              <1> ;--------------------------------------------------------
  2327                              <1> MD_TBL1:        
  2328 000065DA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2329 000065DB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2330 000065DC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2331 000065DD 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2332 000065DE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2333 000065DF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2334 000065E0 FF                  <1> 	DB	0FFH		; DTL
  2335 000065E1 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2336 000065E2 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2337 000065E3 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2338 000065E4 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2339 000065E5 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2340 000065E6 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2341                              <1> ;--------------------------------------------------------
  2342                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2343                              <1> ;--------------------------------------------------------
  2344                              <1> MD_TBL2:        
  2345 000065E7 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2346 000065E8 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2347 000065E9 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2348 000065EA 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2349 000065EB 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2350 000065EC 2A                  <1> 	DB	02AH		; GAP LENGTH
  2351 000065ED FF                  <1> 	DB	0FFH		; DTL
  2352 000065EE 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2353 000065EF F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2354 000065F0 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2355 000065F1 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2356 000065F2 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2357 000065F3 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2358                              <1> ;--------------------------------------------------------
  2359                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2360                              <1> ;--------------------------------------------------------
  2361                              <1> MD_TBL3:
  2362 000065F4 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2363 000065F5 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2364 000065F6 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2365 000065F7 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2366 000065F8 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2367 000065F9 1B                  <1> 	DB	01BH		; GAP LENGTH
  2368 000065FA FF                  <1> 	DB	0FFH		; DTL
  2369 000065FB 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2370 000065FC F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2371 000065FD 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2372 000065FE 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2373 000065FF 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2374 00006600 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2375                              <1> ;--------------------------------------------------------
  2376                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2377                              <1> ;--------------------------------------------------------
  2378                              <1> MD_TBL4:
  2379 00006601 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2380 00006602 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2381 00006603 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2382 00006604 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2383 00006605 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2384 00006606 2A                  <1> 	DB	02AH		; GAP LENGTH
  2385 00006607 FF                  <1> 	DB	0FFH		; DTL
  2386 00006608 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2387 00006609 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2388 0000660A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2389 0000660B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2390 0000660C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2391 0000660D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2392                              <1> ;--------------------------------------------------------
  2393                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2394                              <1> ;--------------------------------------------------------
  2395                              <1> MD_TBL5:
  2396 0000660E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2397 0000660F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2398 00006610 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2399 00006611 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2400 00006612 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2401 00006613 2A                  <1> 	DB	02AH		; GAP LENGTH
  2402 00006614 FF                  <1> 	DB	0FFH		; DTL
  2403 00006615 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2404 00006616 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2405 00006617 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2406 00006618 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2407 00006619 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2408 0000661A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2409                              <1> ;--------------------------------------------------------
  2410                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2411                              <1> ;--------------------------------------------------------
  2412                              <1> MD_TBL6:
  2413 0000661B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2414 0000661C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2415 0000661D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2416 0000661E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2417 0000661F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2418 00006620 1B                  <1> 	DB	01BH		; GAP LENGTH
  2419 00006621 FF                  <1> 	DB	0FFH		; DTL
  2420 00006622 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2421 00006623 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2422 00006624 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2423 00006625 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2424 00006626 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2425 00006627 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2426                              <1> 
  2427                              <1> 
  2428                              <1> ; << diskette.inc >>
  2429                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2430                              <1> ;
  2431                              <1> ;----------------------------------------
  2432                              <1> ;	ROM BIOS DATA AREAS		:
  2433                              <1> ;----------------------------------------
  2434                              <1> 
  2435                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2436                              <1> 
  2437                              <1> ;----------------------------------------
  2438                              <1> ;	FIXED DISK DATA AREAS		:
  2439                              <1> ;----------------------------------------
  2440                              <1> 
  2441                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2442                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2443                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2444                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2445                              <1> 
  2446                              <1> ;----------------------------------------
  2447                              <1> ;	ADDITIONAL MEDIA DATA		:
  2448                              <1> ;----------------------------------------
  2449                              <1> 
  2450                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2451                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2452                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2453                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2454                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2455                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2456                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2457                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2458                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2459                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2460                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2461                              <1> 
  2462                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2463                              <1> ;
  2464                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2465                              <1> 
  2466                              <1> ERR_TBL:
  2467 00006628 E0                  <1> 	db	NO_ERR
  2468 00006629 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2469 0000662D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2470                              <1> 
  2471                              <1> ; 17/12/2014 (mov ax, [cfd])
  2472                              <1> ; 11/12/2014
  2473 00006631 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2474                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2475 00006632 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2476                              <1> 					; (initial value of 'pfd 
  2477                              <1> 					; must be different then 'cfd' value
  2478                              <1> 					; to force updating/initializing
  2479                              <1> 					; current drive parameters) 
  2480 00006633 90                  <1> align 2
  2481                              <1> 
  2482 00006634 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2483                              <1> 			      ; (170h)
  2484 00006636 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2485                              <1> 
  2486                              <1> ; 05/01/2015 
  2487 00006638 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2488                              <1> 
  2489                              <1> ; *****************************************************************************
  2206                                  ;;;
  2207                                  
  2208 00006639 90                      Align 2
  2209                                  
  2210                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2211 0000663A 00                      boot_drv:    db 0 ; boot drive number (physical)
  2212                                  ; 24/11/2014
  2213 0000663B 00                      drv:	     db 0 
  2214 0000663C 00                      last_drv:    db 0 ; last hdd
  2215 0000663D 00                      hdc:         db 0  ; number of hard disk drives
  2216                                  		     ; (present/detected)
  2217                                  ;
  2218                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2219                                  ; Physical drive type & flags
  2220 0000663E 00                      fd0_type:    db 0  ; floppy drive type
  2221 0000663F 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2222                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2223                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2224                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2225                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2226 00006640 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2227 00006641 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2228 00006642 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2229 00006643 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2230                                  		     ; bit 0 - Fixed disk access subset supported
  2231                                  		     ; bit 1 - Drive locking and ejecting
  2232                                  		     ; bit 2 - Enhanced disk drive support
  2233                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2234                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2235                                  		     ; will interpret it as 'LBA ready'!)		
  2236                                  
  2237                                  ; 11/03/2015 - 10/07/2015
  2238 00006644 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2238 0000664D 0000000000         
  2239 00006652 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2239 0000665B 0000000000         
  2240 00006660 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2240 00006669 0000000000         
  2241 0000666E 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2241 00006677 000000000000000000-
  2241 00006680 000000000000000000-
  2241 00006689 00                 
  2242 0000668A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2243 00006691 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2244                                  ;
  2245                                  
  2246                                  ; 27/08/2014
  2247                                  scr_row:
  2248 00006698 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2249                                  scr_col:
  2250 0000669C 00000000                	dd 0
  2251                                  
  2252                                  ;; 14/08/2015
  2253                                  ;;msgPM:
  2254                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2255                                  msgKVER:
  2256                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2257 000066A0 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [26/02/2022]", 0	
  2257 000066A9 582033383620763120-
  2257 000066B2 2D204B65726E656C20-
  2257 000066BB 76302E322E302E3138-
  2257 000066C4 205B32362F30322F32-
  2257 000066CD 3032325D00         
  2258                                  
  2259                                  Align 2
  2260                                  
  2261                                  ; 20/08/2014
  2262                                    ; /* This is the default interrupt "handler" :-) */ 
  2263                                    ; Linux v0.12 (head.s)
  2264                                  int_msg:
  2265 000066D2 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2265 000066DB 6E7465727275707420-
  2265 000066E4 212000             
  2266                                  
  2267 000066E7 90                      Align 2  
  2268                                  
  2269                                  ; 21/08/2014
  2270                                  timer_msg:
  2271 000066E8 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2271 000066F1 542032306829202120-
  2271 000066FA 54696D657220496E74-
  2271 00006703 657272757074203A20 
  2272                                  tcountstr:
  2273 0000670C 303030303020            	db "00000 "
  2274 00006712 00                      	db 0
  2275                                  
  2276 00006713 90                      Align 2
  2277                                  	; 21/08/2014
  2278                                  exc_msg:
  2279 00006714 435055206578636570-     	db "CPU exception ! "
  2279 0000671D 74696F6E202120     
  2280                                  excnstr: 		; 25/08/2014
  2281 00006724 3F3F68202045495020-     	db "??h", "  EIP : "
  2281 0000672D 3A20               
  2282                                  EIPstr: ; 29/08/2014
  2283 0000672F 00<rep Ch>              	times 12 db 0
  2284                                  rtc_msg:
  2285 0000673B 5265616C2054696D65-     	db "Real Time Clock - "
  2285 00006744 20436C6F636B202D20 
  2286                                  datestr:
  2287 0000674D 30302F30302F303030-     	db "00/00/0000"
  2287 00006756 30                 
  2288 00006757 20                      	db " "
  2289                                  daystr:
  2290 00006758 44415920                	db "DAY "
  2291                                  timestr:	
  2292 0000675C 30303A30303A3030                db "00:00:00"
  2293 00006764 20                      	db " "
  2294 00006765 00                      	db 0 
  2295                                  
  2296                                  daytmp:
  2297                                  	; 28/02/2015
  2298 00006766 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2298 0000676F 4F4E20545545205745-
  2298 00006778 442054485520465249-
  2298 00006781 2053415420         
  2299                                  
  2300 00006786 FF                      ptime_seconds: db 0FFh
  2301                                  
  2302                                  	; 23/02/2015
  2303                                  	; 25/08/2014
  2304                                  ;scounter:
  2305                                  ;	db 5
  2306                                  ;	db 19
  2307                                  
  2308                                  ;; 05/11/2014
  2309                                  ;msg_out_of_memory:
  2310                                  ;	db 	07h, 0Dh, 0Ah
  2311                                  ;	db      'Insufficient memory ! '
  2312                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2313                                  ; 	db	0Dh, 0Ah, 0
  2314                                  	;
  2315                                  setup_error_msg:
  2316 00006787 0D0A                    	db 0Dh, 0Ah
  2317 00006789 4469736B2053657475-     	db 'Disk Setup Error!' 
  2317 00006792 70204572726F7221   
  2318 0000679A 0D0A00                  	db 0Dh, 0Ah,0
  2319                                  
  2320                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2321                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2322                                  ;	  db 0 ; upper left row (for scroll)	
  2323                                  
  2324                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2325                                  ;	  db 24 ; lower right row (for scroll)
  2326                                  
  2327                                  
  2328                                  ; 06/11/2014 (Temporary Data)
  2329                                  ; Memory Information message
  2330                                  ; 14/08/2015
  2331                                  msg_memory_info:
  2332 0000679D 07                      	db	07h
  2333 0000679E 0D0A                    	db	0Dh, 0Ah
  2334                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2335 000067A0 546F74616C206D656D-     	db	"Total memory : "
  2335 000067A9 6F7279203A20       
  2336                                  mem_total_b_str: ; 10 digits
  2337 000067AF 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2337 000067B8 302062797465730D0A 
  2338 000067C1 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2338 000067CA 202020202020202020 
  2339                                  mem_total_p_str: ; 7 digits
  2340 000067D3 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2340 000067DC 616765730D0A       
  2341 000067E2 0D0A                    	db 	0Dh, 0Ah
  2342 000067E4 46726565206D656D6F-     	db	"Free memory  : "
  2342 000067ED 727920203A20       
  2343                                  free_mem_b_str:  ; 10 digits
  2344 000067F3 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2344 000067FC 3F2062797465730D0A 
  2345 00006805 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2345 0000680E 202020202020202020 
  2346                                  free_mem_p_str:  ; 7 digits
  2347 00006817 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2347 00006820 616765730D0A       
  2348 00006826 0D0A00                  	db	0Dh, 0Ah, 0
  2349                                  
  2350                                  dsk_ready_msg:
  2351 00006829 0D0A                    	db 	0Dh, 0Ah
  2352                                  dsktype:
  2353 0000682B 6664                    	db	'fd'
  2354                                  dskx:
  2355 0000682D 30                      	db	'0'
  2356 0000682E 20                      	db	20h
  2357 0000682F 697320524541445920-     	db 	'is READY ...'
  2357 00006838 2E2E2E             
  2358 0000683B 00                      	db 	0
  2359                                  nextline:
  2360 0000683C 0D0A00                  	db 	0Dh, 0Ah, 0
  2361                                  
  2362                                  ; KERNEL - SYSINIT Messages
  2363                                  ; 24/08/2015
  2364                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2365                                  ; 14/07/2013
  2366                                  ;kernel_init_err_msg:
  2367                                  ;	db 0Dh, 0Ah
  2368                                  ;	db 07h
  2369                                  ;	db 'Kernel initialization ERROR !'
  2370                                  ;	db 0Dh, 0Ah, 0 
  2371                                  ; 24/08/2015
  2372                                  ;;; (temporary kernel init message has been removed
  2373                                  ;;;  from 'sys_init' code)
  2374                                  ;kernel_init_ok_msg: 
  2375                                  ;	db 0Dh, 0Ah
  2376                                  ;	db 07h
  2377                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2378                                  ;	db 0Dh, 0Ah
  2379                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2380                                  ;	db 0Dh, 0Ah, 0
  2381                                  panic_msg:
  2382 0000683F 0D0A07                  	db 0Dh, 0Ah, 07h
  2383 00006842 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2383 0000684B 726E656C2050616E69-
  2383 00006854 632021             
  2384 00006857 0D0A00                  	db 0Dh, 0Ah, 0
  2385                                  etc_init_err_msg:
  2386 0000685A 0D0A                    	db 0Dh, 0Ah
  2387 0000685C 07                      	db 07h
  2388 0000685D 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2388 00006866 74632F696E69742021-
  2388 0000686F 3F                 
  2389 00006870 0D0A00                  	db 0Dh, 0Ah, 0
  2390                                  
  2391                                  ; 10/05/2015
  2392                                  badsys_msg:
  2393 00006873 0D0A                    	db 0Dh, 0Ah
  2394 00006875 07                      	db 07h
  2395 00006876 496E76616C69642053-     	db 'Invalid System Call !'
  2395 0000687F 797374656D2043616C-
  2395 00006888 6C2021             
  2396 0000688B 0D0A                    	db 0Dh, 0Ah
  2397 0000688D 4541583A20              	db 'EAX: '
  2398                                  bsys_msg_eax:
  2399 00006892 303030303030303068      	db '00000000h'
  2400 0000689B 0D0A                    	db 0Dh, 0Ah
  2401 0000689D 4549503A20              	db 'EIP: '
  2402                                  bsys_msg_eip:
  2403 000068A2 303030303030303068      	db '00000000h' 
  2404 000068AB 0D0A00                  	db 0Dh, 0Ah, 0
  2405                                  
  2406                                  BSYS_M_SIZE equ $ - badsys_msg
  2407                                  
  2408                                  
  2409                                  align 2
  2410                                  
  2411                                  ; EPOCH Variables
  2412                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2413                                  ; 09/04/2013 epoch variables
  2414                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2415                                  ;
  2416 000068AE B207                    year: 	dw 1970
  2417 000068B0 0100                    month: 	dw 1
  2418 000068B2 0100                    day: 	dw 1
  2419 000068B4 0000                    hour: 	dw 0
  2420 000068B6 0000                    minute: dw 0
  2421 000068B8 0000                    second: dw 0
  2422                                  
  2423                                  DMonth:
  2424 000068BA 0000                    	dw 0
  2425 000068BC 1F00                    	dw 31
  2426 000068BE 3B00                    	dw 59
  2427 000068C0 5A00                    	dw 90
  2428 000068C2 7800                    	dw 120
  2429 000068C4 9700                    	dw 151
  2430 000068C6 B500                    	dw 181
  2431 000068C8 D400                    	dw 212
  2432 000068CA F300                    	dw 243
  2433 000068CC 1101                    	dw 273
  2434 000068CE 3001                    	dw 304
  2435 000068D0 4E01                    	dw 334
  2436                                  
  2437                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2438 000068D2 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2439                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2440 000068D4 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2441                                  		   ;   between 16 MB and 4 GB.
  2442                                  
  2443 000068D6 90<rep Ah>              align 16
  2444                                  
  2445                                  bss_start:
  2446                                  
  2447                                  ABSOLUTE bss_start
  2448                                  
  2449                                  	; 11/03/2015
  2450                                  	; Interrupt Descriptor Table (20/08/2014)
  2451                                  idt:
  2452 000068E0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2453                                  idt_end:
  2454                                  
  2455                                  ;alignb 4
  2456                                  
  2457                                  task_state_segment:
  2458                                  	; 24/03/2015
  2459 00006AE0 ????                    tss.link:   resw 1
  2460 00006AE2 ????                    	    resw 1
  2461                                  ; tss offset 4	
  2462 00006AE4 ????????                tss.esp0:   resd 1
  2463 00006AE8 ????                    tss.ss0:    resw 1
  2464 00006AEA ????                    	    resw 1	
  2465 00006AEC ????????                tss.esp1:   resd 1
  2466 00006AF0 ????                    tss.ss1:    resw 1
  2467 00006AF2 ????                    	    resw 1 	
  2468 00006AF4 ????????                tss.esp2:   resd 1
  2469 00006AF8 ????                    tss.ss2:    resw 1
  2470 00006AFA ????                    	    resw 1
  2471                                  ; tss offset 28
  2472 00006AFC ????????                tss.CR3:    resd 1
  2473 00006B00 ????????                tss.eip:    resd 1
  2474 00006B04 ????????                tss.eflags: resd 1
  2475                                  ; tss offset 40
  2476 00006B08 ????????                tss.eax:    resd 1		 		
  2477 00006B0C ????????                tss.ecx:    resd 1
  2478 00006B10 ????????                tss.edx:    resd 1
  2479 00006B14 ????????                tss.ebx:    resd 1
  2480 00006B18 ????????                tss.esp:    resd 1
  2481 00006B1C ????????                tss.ebp:    resd 1
  2482 00006B20 ????????                tss.esi:    resd 1
  2483 00006B24 ????????                tss.edi:    resd 1
  2484                                  ; tss offset 72
  2485 00006B28 ????                    tss.ES:     resw 1
  2486 00006B2A ????                    	    resw 1	
  2487 00006B2C ????                    tss.CS:	    resw 1
  2488 00006B2E ????                    	    resw 1
  2489 00006B30 ????                    tss.SS:	    resw 1
  2490 00006B32 ????                    	    resw 1
  2491 00006B34 ????                    tss.DS:	    resw 1
  2492 00006B36 ????                    	    resw 1
  2493 00006B38 ????                    tss.FS:	    resw 1
  2494 00006B3A ????                    	    resw 1
  2495 00006B3C ????                    tss.GS:	    resw 1
  2496 00006B3E ????                    	    resw 1		
  2497 00006B40 ????                    tss.LDTR:   resw 1
  2498 00006B42 ????                    	    resw 1
  2499                                  ; tss offset 100		
  2500 00006B44 ????                    	    resw 1		
  2501 00006B46 ????                    tss.IOPB:   resw 1
  2502                                  ; tss offset 104 
  2503                                  tss_end:
  2504                                  
  2505 00006B48 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2506                                  		    ; (Physical address = Virtual address)	 	
  2507 00006B4C ????????                memory_size: resd 1 ; memory size in pages
  2508 00006B50 ????????                free_pages:  resd 1 ; number of free pages		
  2509 00006B54 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2510                                  		    ; first free page search
  2511 00006B58 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2512                                  		    ; next free page search will be
  2513                                  		    ; stopped after it. (end of M.A.T.)
  2514 00006B5C ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2515                                  		    ; first free page search
  2516                                  		    ; will be started on it. (for user)
  2517 00006B60 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2518                                  
  2519                                  ;;;
  2520                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2521                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2522 00006B64 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2523                                  		    ; NOTE: active page only
  2524 00006B66 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2525                                  active_page: 
  2526 00006B76 ??                      ptty: 	     resb 1 ; current tty
  2527                                  ; 01/07/2015
  2528 00006B77 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2529                                  ; 26/10/2015
  2530                                  ; 07/09/2014
  2531 00006B78 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2532                                  
  2533                                  ; 21/08/2014
  2534 00006B8C ????????                tcount:	     resd 1
  2535                                  
  2536                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2537 00006B90 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2538                                  
  2539                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2540                                  ; (open mode locks for pseudo TTYs)
  2541                                  ; [ major tty locks (return error in any conflicts) ]
  2542 00006B94 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2543                                  
  2544                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2545                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2546 00006BA8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2547                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2548                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2549                                  ;; 0 means serial port is not available 
  2550                                  ;;comprm: ; 25/06/2014
  2551 00006BB2 ??                      com1p:       resb 1 ;;0E3h
  2552 00006BB3 ??                      com2p:       resb 1 ;;0E3h
  2553                                  
  2554                                  ; 17/11/2015
  2555                                  ; request for response (from the terminal)	
  2556 00006BB4 ????                    req_resp:     resw 1 			
  2557                                  ; 07/11/2015
  2558 00006BB6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2559                                  		    ; (0= COM1, 1= COM2)
  2560                                  ; 09/11/2015
  2561 00006BB7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2562                                  ; 07/11/2015
  2563 00006BB8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2564 00006BBA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2565                                  
  2566                                  ; 23/10/2015
  2567                                  ; SERIAL PORTS - COMMUNICATION MODES
  2568                                  ; (Retro UNIX 386 v1 feature only!)
  2569                                  ; 0 - command mode (default/initial mode)
  2570                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2571                                  ;;; communication modes for future versions:  
  2572                                  ; // 2 - keyboard mode (ascii+scancode input)
  2573                                  ; // 3 - mouse mode
  2574                                  ; // 4 - device control (output) mode
  2575                                  ; VALID COMMANDS for current version:
  2576                                  ; 	'LOGIN'
  2577                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2578                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2579                                  ;  Login response: db 0FFh, 'login', 0
  2580                                  ;	 ("login request accepted, wait for login prompt") 
  2581                                  ; When a login requests is received and acknowledged (by
  2582                                  ; serial port interrupt handler (communication procedure),
  2583                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2584                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2585                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2586                                  ; 
  2587                                  ; 'sys connect' system call is used to change communication mode
  2588                                  ; except 'LOGIN' command which is used to start terminal mode
  2589                                  ; by using (COM port) terminal.
  2590                                  
  2591                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2592                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2593                                  ;com1mode:    resb 1 ; communication mode for COM1
  2594                                  ;com1com:     resb 1 ; communication command for COM1
  2595                                  ;com2mode:    resb 1 ; communication mode for COM1
  2596                                  ;com2com      resb 1 ; communication command for COM1
  2597                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2598                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2599                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2600                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2601                                  
  2602                                  ; 22/08/2014 (RTC)
  2603                                  ; (Packed BCD)
  2604 00006BBC ??                      time_seconds: resb 1
  2605 00006BBD ??                      time_minutes: resb 1
  2606 00006BBE ??                      time_hours:   resb 1
  2607 00006BBF ??                      date_wday:    resb 1
  2608 00006BC0 ??                      date_day:     resb 1
  2609 00006BC1 ??                      date_month:   resb 1			
  2610 00006BC2 ??                      date_year:    resb 1
  2611 00006BC3 ??                      date_century: resb 1
  2612                                  
  2613                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2614                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2615                              <1> ; Last Modification: 10/07/2015
  2616                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2617                              <1> ;
  2618                              <1> ; *****************************************************************************
  2619                              <1> 
  2620                              <1> alignb 2
  2621                              <1> 
  2622                              <1> ;----------------------------------------
  2623                              <1> ;	TIMER DATA AREA 		:
  2624                              <1> ;----------------------------------------
  2625                              <1> 
  2626                              <1> TIMER_LH:	; 16/02/205
  2627 00006BC4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2628 00006BC6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2629 00006BC8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2630                              <1> 
  2631                              <1> ;----------------------------------------
  2632                              <1> ;	DISKETTE DATA AREAS		:
  2633                              <1> ;----------------------------------------
  2634                              <1> 
  2635 00006BC9 ??                  <1> SEEK_STATUS:	resb	1
  2636 00006BCA ??                  <1> MOTOR_STATUS:	resb	1
  2637 00006BCB ??                  <1> MOTOR_COUNT:	resb	1
  2638 00006BCC ??                  <1> DSKETTE_STATUS:	resb	1
  2639 00006BCD ??????????????      <1> NEC_STATUS:	resb	7
  2640                              <1> 
  2641                              <1> ;----------------------------------------
  2642                              <1> ;	ADDITIONAL MEDIA DATA		:
  2643                              <1> ;----------------------------------------
  2644                              <1> 
  2645 00006BD4 ??                  <1> LASTRATE:	resb 	1
  2646 00006BD5 ??                  <1> HF_STATUS:	resb 	1
  2647 00006BD6 ??                  <1> HF_ERROR:	resb 	1
  2648 00006BD7 ??                  <1> HF_INT_FLAG:	resb 	1
  2649 00006BD8 ??                  <1> HF_CNTRL:	resb 	1
  2650 00006BD9 ????????            <1> DSK_STATE:	resb 	4
  2651 00006BDD ????                <1> DSK_TRK:	resb 	2
  2652                              <1> 
  2653                              <1> ;----------------------------------------
  2654                              <1> ;	FIXED DISK DATA AREAS		:
  2655                              <1> ;----------------------------------------
  2656                              <1> 
  2657 00006BDF ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2658 00006BE0 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2659 00006BE1 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2660                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2661                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2662                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2663                              <1> 
  2664 00006BE2 ????                <1> alignb 4
  2665                              <1> 
  2666                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2667                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2668                              <1> HF_TBL_VEC: ; 22/12/2014	
  2669 00006BE4 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2670 00006BE8 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2671 00006BEC ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2672 00006BF0 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2673                              <1> 
  2674                              <1> ; 03/01/2015
  2675 00006BF4 ??                  <1> LBAMode:     	resb	1
  2676                              <1> 
  2677                              <1> ; *****************************************************************************
  2614                                  
  2615                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2616                                  
  2617                                  ;alignb 2
  2618                                  
  2619                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2620                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYSX.INC (ux.s)
  2621                              <1> ; Last Modification: 26/02/2022
  2622                              <1> ;
  2623                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2624                              <1> ; (Modified from 
  2625                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2626                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2627                              <1> ; ----------------------------------------------------------------------------
  2628                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2629                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2630                              <1> ; <Bell Laboratories (17/3/1972)>
  2631                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2632                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2633                              <1> ; ****************************************************************************
  2634                              <1> ; 13/11/2015
  2635                              <1> 
  2636 00006BF5 ??                  <1> alignb 2
  2637                              <1> 
  2638                              <1> inode:
  2639                              <1> 	; 11/03/2013. 
  2640                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2641                              <1> 	;i.
  2642                              <1> 
  2643 00006BF6 ????                <1> 	i.flgs:	 resw 1
  2644 00006BF8 ??                  <1> 	i.nlks:	 resb 1
  2645 00006BF9 ??                  <1> 	i.uid:	 resb 1
  2646 00006BFA ????                <1>         i.size:  resw 1 ; size
  2647 00006BFC <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2648 00006C0C ????????            <1> 	i.ctim:	 resd 1
  2649 00006C10 ????????            <1> 	i.mtim:	 resd 1
  2650 00006C14 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2651                              <1> 
  2652                              <1> I_SIZE	equ $ - inode 
  2653                              <1> 
  2654                              <1> process:
  2655                              <1> 	; 26/02/2022
  2656                              <1> 	; 04/02/2022
  2657                              <1> 	; 06/05/2015
  2658                              <1> 	; 11/03/2013 - 05/02/2014
  2659                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2660                              <1> 	;p.
  2661                              <1> 	
  2662 00006C16 <res 20h>           <1>         p.pid:   resw nproc
  2663 00006C36 <res 20h>           <1>         p.ppid:  resw nproc
  2664                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2665 00006C56 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2666                              <1> 	; 26/02/2022 (p.waitc is not used)
  2667                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2668 00006C66 <res 10h>           <1> 	p.link:	 resb nproc
  2669 00006C76 <res 10h>           <1> 	p.stat:	 resb nproc
  2670                              <1> 
  2671                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2672 00006C86 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2673                              <1> 			    ; 'user' structure	
  2674                              <1> 
  2675                              <1> 
  2676                              <1> P_SIZE	equ $ - process
  2677                              <1> 
  2678                              <1> 
  2679                              <1> ; fsp table (original UNIX v1)
  2680                              <1> ;
  2681                              <1> ;Entry
  2682                              <1> ;          15                                      0
  2683                              <1> ;  1     |---|---------------------------------------|
  2684                              <1> ;        |r/w|       i-number of open file           |
  2685                              <1> ;        |---|---------------------------------------| 
  2686                              <1> ;        |               device number               |
  2687                              <1> ;        |-------------------------------------------|
  2688                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2689                              <1> ;        |-------------------------------------------| 
  2690                              <1> ;        |  flag that says    | number of processes  |
  2691                              <1> ;        |   file deleted     | that have file open  |
  2692                              <1> ;        |-------------------------------------------| 
  2693                              <1> ;  2     |                                           |
  2694                              <1> ;        |-------------------------------------------| 
  2695                              <1> ;        |                                           |
  2696                              <1> ;        |-------------------------------------------|
  2697                              <1> ;        |                                           |
  2698                              <1> ;        |-------------------------------------------|
  2699                              <1> ;        |                                           |
  2700                              <1> ;        |-------------------------------------------| 
  2701                              <1> ;  3     |                                           | 
  2702                              <1> ;        |                                           |  
  2703                              <1> ;
  2704                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2705                              <1> 
  2706                              <1> 
  2707                              <1> ; 15/04/2015
  2708 00006CC6 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2709 00006EBA <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2710 00006EDA ????                <1> ii:	 resw 1
  2711 00006EDC ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2712 00006EDE ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2713                              <1> ; 18/05/2015
  2714                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2715                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2716                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2717                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2718                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2719                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2720                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2721                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2722                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2723                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2724                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2725 00006EE0 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2726                              <1> 	        ; as above, for physical drives numbers in following table
  2727 00006EE1 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2728                              <1> ; 15/04/2015
  2729 00006EE2 ??                  <1> active:	 resb 1 
  2730 00006EE3 ??                  <1> 	 resb 1 ; 09/06/2015
  2731 00006EE4 ????                <1> mnti:	 resw 1
  2732 00006EE6 ????                <1> mpid:	 resw 1
  2733 00006EE8 ????                <1> rootdir: resw 1
  2734                              <1> ; 14/02/2014
  2735                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2736                              <1> ;		      Single level run queue
  2737                              <1> ;		      (in order to solve sleep/wakeup lock)
  2738 00006EEA ????                <1> runq:	 resw 1
  2739 00006EEC ??                  <1> imod:	 resb 1
  2740 00006EED ??                  <1> smod:	 resb 1
  2741 00006EEE ??                  <1> mmod:	 resb 1
  2742 00006EEF ??                  <1> sysflg:	 resb 1
  2743                              <1> 
  2744                              <1> alignb 4
  2745                              <1> 
  2746                              <1> user:
  2747                              <1> 	; 18/10/2015
  2748                              <1> 	; 12/10/2015
  2749                              <1> 	; 21/09/2015
  2750                              <1> 	; 24/07/2015
  2751                              <1> 	; 16/06/2015
  2752                              <1> 	; 09/06/2015
  2753                              <1> 	; 11/05/2015
  2754                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2755                              <1> 	; 10/10/2013
  2756                              <1> 	; 11/03/2013. 
  2757                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2758                              <1> 	;u.
  2759                              <1> 
  2760 00006EF0 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2761 00006EF4 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2762 00006EF8 ????????            <1> 	u.r0:	  resd 1 ; eax
  2763 00006EFC ????                <1> 	u.cdir:	  resw 1
  2764 00006EFE <res Ah>            <1> 	u.fp:	  resb 10
  2765 00006F08 ????????            <1> 	u.fofp:	  resd 1
  2766 00006F0C ????????            <1> 	u.dirp:	  resd 1
  2767 00006F10 ????????            <1> 	u.namep:  resd 1
  2768 00006F14 ????????            <1> 	u.off:	  resd 1
  2769 00006F18 ????????            <1> 	u.base:	  resd 1
  2770 00006F1C ????????            <1> 	u.count:  resd 1
  2771 00006F20 ????????            <1> 	u.nread:  resd 1
  2772 00006F24 ????????            <1> 	u.break:  resd 1 ; break
  2773 00006F28 ????                <1> 	u.ttyp:	  resw 1 
  2774 00006F2A <res Ah>            <1> 	u.dirbuf: resb 10
  2775                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2776 00006F34 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2777 00006F35 ??                  <1> 	u.pri:	  resb 1 ; 
  2778 00006F36 ????                <1> 	u.intr:	  resw 1
  2779 00006F38 ????                <1> 	u.quit:	  resw 1
  2780                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2781 00006F3A ????                <1> 	u.ilgins: resw 1
  2782 00006F3C ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2783 00006F3E ??                  <1> 	u.uid:	  resb 1 ; uid
  2784 00006F3F ??                  <1> 	u.ruid:	  resb 1
  2785 00006F40 ??                  <1> 	u.bsys:	  resb 1
  2786 00006F41 ??                  <1> 	u.uno:	  resb 1
  2787 00006F42 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2788                              <1> 	; tty number (rtty, rcvt, wtty)
  2789 00006F46 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2790                              <1> 	; last error number
  2791 00006F47 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2792                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2793 00006F4B ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2794 00006F4F ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2795 00006F53 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2796 00006F57 ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2797                              <1> 	;u.pncount: resw 1 
  2798                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2799                              <1> 	;u.pnbase:  resd 1 
  2800                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2801                              <1> 			 ; 09/06/2015
  2802 00006F59 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2803 00006F5A ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2804                              <1> 			 ; 24/07/2015 - 24/06/2015
  2805                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2806                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2807                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2808                              <1>  			 ; 24/06/2015	  	
  2809                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2810                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2811                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2812 00006F5B ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2813                              <1> 
  2814 00006F5F ??                  <1> alignb 4
  2815                              <1> 
  2816                              <1> U_SIZE	equ $ - user
  2817                              <1> 
  2818                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2819 00006F60 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2820 00006F64 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2821 00006F68 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2822 00006F6C ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2823 00006F6E ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2824 00006F70 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2825                              <1> 
  2826                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2827                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2828 00006F74 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2829 00006F75 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2830 00006F76 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2831 00006F77 ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2832                              <1> 
  2833                              <1> ;alignb 4
  2834                              <1> 
  2835                              <1> ; 22/08/2015
  2836 00006F78 <res C30h>          <1> buffer: resb nbuf * 520
  2837                              <1> 
  2838 00007BA8 ????????????????    <1> sb0:	resd 2
  2839                              <1> ;s:
  2840                              <1> ; (root disk) super block buffer
  2841                              <1> systm:
  2842                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2843                              <1> 	; 11/03/2013. 
  2844                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2845                              <1> 	;s.
  2846                              <1> 
  2847 00007BB0 ????                <1> 	resw 1
  2848 00007BB2 <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2849 00007D1A ????                <1> 	resw 1
  2850 00007D1C <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2851                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2852 00007D3C ????????            <1> 	s.time:	 resd 1
  2853 00007D40 ????????            <1> 	s.syst:	 resd 1
  2854 00007D44 ????????            <1>         s.wait_: resd 1 ; wait
  2855 00007D48 ????????            <1> 	s.idlet: resd 1
  2856 00007D4C ????????            <1> 	s.chrgt: resd 1
  2857 00007D50 ????                <1> 	s.drerr: resw 1
  2858                              <1> 
  2859                              <1> S_SIZE	equ $ - systm
  2860                              <1> 
  2861 00007D52 <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2862                              <1> 
  2863 00007DB0 ????????????????    <1> sb1:	resd 2
  2864                              <1> ; (mounted disk) super block buffer
  2865                              <1> mount:	
  2866 00007DB8 <res 200h>          <1> 	resb 512  ; 03/06/2015
  2867                              <1> 
  2868                              <1> ;/ ux -- unix
  2869                              <1> ;
  2870                              <1> ;systm:
  2871                              <1> ;
  2872                              <1> ;	.=.+2
  2873                              <1> ;	.=.+128.
  2874                              <1> ;	.=.+2
  2875                              <1> ;	.=.+64.
  2876                              <1> ;	s.time: .=.+4
  2877                              <1> ;	s.syst: .=.+4
  2878                              <1> ;	s.wait: .=.+4
  2879                              <1> ;	s.idlet:.=.+4
  2880                              <1> ;	s.chrgt:.=.+4
  2881                              <1> ;	s.drerr:.=.+2
  2882                              <1> ;inode:
  2883                              <1> ;	i.flgs: .=.+2
  2884                              <1> ;	i.nlks: .=.+1
  2885                              <1> ;	i.uid:  .=.+1
  2886                              <1> ;	i.size: .=.+2
  2887                              <1> ;	i.dskp: .=.+16.
  2888                              <1> ;	i.ctim: .=.+4
  2889                              <1> ;	i.mtim: .=.+4
  2890                              <1> ;	. = inode+32.
  2891                              <1> ;mount:	.=.+1024.
  2892                              <1> ;proc:
  2893                              <1> ;	p.pid:  .=.+[2*nproc]
  2894                              <1> ;	p.dska: .=.+[2*nproc]
  2895                              <1> ;	p.ppid: .=.+[2*nproc]
  2896                              <1> ;	p.break:.=.+[2*nproc]
  2897                              <1> ;	p.link: .=.+nproc
  2898                              <1> ;	p.stat: .=.+nproc
  2899                              <1> ;tty:
  2900                              <1> ;	. = .+[ntty*8.]
  2901                              <1> ;fsp:	.=.+[nfiles*8.]
  2902                              <1> ;bufp:	.=.+[nbuf*2]+6
  2903                              <1> ;sb0:	.=.+8
  2904                              <1> ;sb1:	.=.+8
  2905                              <1> ;swp:	.=.+8
  2906                              <1> ;ii:	.=.+2
  2907                              <1> ;idev:	.=.+2
  2908                              <1> ;cdev:	.=.+2
  2909                              <1> ;deverr: .=.+12.
  2910                              <1> ;active: .=.+2
  2911                              <1> ;rfap:	.=.+2
  2912                              <1> ;rkap:	.=.+2
  2913                              <1> ;tcap:	.=.+2
  2914                              <1> ;tcstate:.=.+2
  2915                              <1> ;tcerrc: .=.+2
  2916                              <1> ;mnti:	.=.+2
  2917                              <1> ;mntd:	.=.+2
  2918                              <1> ;mpid:	.=.+2
  2919                              <1> ;clockp: .=.+2
  2920                              <1> ;rootdir:.=.+2
  2921                              <1> ;toutt:	.=.+16.
  2922                              <1> ;touts: .=.+32.
  2923                              <1> ;runq:	.=.+6
  2924                              <1> ;
  2925                              <1> ;wlist:	.=.+40.
  2926                              <1> ;cc:	.=.+30.
  2927                              <1> ;cf:	.=.+31.
  2928                              <1> ;cl:	.=.+31.
  2929                              <1> ;clist:	.=.+510.
  2930                              <1> ;imod:	.=.+1
  2931                              <1> ;smod:	.=.+1
  2932                              <1> ;mmod:	.=.+1
  2933                              <1> ;uquant: .=.+1
  2934                              <1> ;sysflg: .=.+1
  2935                              <1> ;pptiflg:.=.+1
  2936                              <1> ;ttyoch: .=.+1
  2937                              <1> ; .even
  2938                              <1> ; .=.+100.; sstack:
  2939                              <1> ;buffer: .=.+[ntty*140.]
  2940                              <1> ;	.=.+[nbuf*520.]
  2941                              <1> ;
  2942                              <1> ; . = core-64.
  2943                              <1> ;user:
  2944                              <1> ;	u.sp:    .=.+2
  2945                              <1> ;	u.usp:   .=.+2
  2946                              <1> ;	u.r0:    .=.+2
  2947                              <1> ;	u.cdir:  .=.+2
  2948                              <1> ;	u.fp:    .=.+10.
  2949                              <1> ;	u.fofp:  .=.+2
  2950                              <1> ;	u.dirp:  .=.+2
  2951                              <1> ;	u.namep: .=.+2
  2952                              <1> ;	u.off:   .=.+2
  2953                              <1> ;	u.base:  .=.+2
  2954                              <1> ;	u.count: .=.+2
  2955                              <1> ;	u.nread: .=.+2
  2956                              <1> ;	u.break: .=.+2
  2957                              <1> ;	u.ttyp:  .=.+2
  2958                              <1> ;	u.dirbuf:.=.+10.
  2959                              <1> ;	u.pri:   .=.+2
  2960                              <1> ;	u.intr:  .=.+2
  2961                              <1> ;	u.quit:  .=.+2
  2962                              <1> ;	u.emt:   .=.+2
  2963                              <1> ;	u.ilgins:.=.+2
  2964                              <1> ;	u.cdev:  .=.+2
  2965                              <1> ;	u.uid:   .=.+1
  2966                              <1> ;	u.ruid:  .=.+1
  2967                              <1> ;	u.bsys:  .=.+1
  2968                              <1> ;	u.uno:   .=.+1
  2969                              <1> ;. = core
  2620                                  
  2621                                  ; 23/02/2022
  2622                                  ;; Memory (swap) Data (11/03/2015)
  2623                                  ; 09/03/2015
  2624                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2625                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2626                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2627                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2628                                  ;swpd_next:  resd 1 ; next free page block
  2629                                  ;swpd_last:  resd 1 ; last swap page block	
  2630                                  
  2631                                  alignb 4
  2632                                  
  2633                                  ; 10/07/2015
  2634                                  ; 28/08/2014
  2635 00007FB8 ????????                error_code:	resd 1
  2636                                  ; 29/08/2014
  2637 00007FBC ????????                FaultOffset: 	resd 1
  2638                                  ; 21/09/2015
  2639 00007FC0 ????????                PF_Count:	resd 1	; total page fault count
  2640                                  		       	; (for debugging - page fault analyze)
  2641                                  		 	; 'page _fault_handler' (memory.inc)
  2642                                  			; 'sysgeterr' (u9.s)
  2643                                  ; 23/02/2022
  2644 00007FC4 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2645                                  			;  for a system call in next retro unix 386 version)
  2646                                  			; -2 ticks per second-
  2647                                  ;; 21/08/2015
  2648                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2649                                  
  2650                                  bss_end:
  2651                                  
  2652                                  ; 27/12/2013
  2653                                  _end:  ; end of kernel code (and read only data, just before bss)
